Add dependency-confusion protection: scope internal package names and pin the registry
@rupesh-kumar-sah is already working on this.
Since Oct 9, 2026.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 32/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- github-actions, nodejs, python, typescript
- Domain
- build-system, release, security
Research direction
Start with the package names in .github/workflows/build-check.yml, the name and url in the Python setup.py, and the name and private fields in package.json. Before changing anything, confirm with maintainers whether the unscoped PyPI name has ever been published, since renaming a published package is breaking. Done means a CI step fails when the generated name drifts, the setup.py URL points at the real repository, and "private": true is still set.
Written by the indexing model from the issue text.
Description
Problem
package.json is marked "private": true and "name": "alian-structure-api", but CI generates and publishes SDK artifacts under unscoped package names:
# .github/workflows/build-check.yml
name: "@alian-structure/api-client" # TypeScript SDK (scoped)
name: "alian-structure-api" # Python SDK setup.py (unscoped)
The Python SDK's setup.py publishes to PyPI as the unscoped alian-structure-api, with url="https://github.com/alian-structure/structure-api" — a URL that does not match the actual repository location.
The TypeScript SDK is correctly scoped, but nothing in the repository prevents an unscoped name from being introduced later, and nothing verifies that published package names match what is registered.
Why it matters
Unscoped public package names are a dependency-confusion risk. If an attacker (or an employee who loses access) publishes alian-structure-api to PyPI, installs that resolve by name will silently get the attacker's code — which for an SDK means it runs inside every consumer's application with access to their environment and credentials.
The URL mismatch compounds it: nobody can tell which repository the package legitimately originates from.
Suggested Direction
- Scope every publishable name. Prefer
alian-structure-*or an org scope for both ecosystems. For Python, a package name and an import name can differ, so the import path can stay readable while the distribution is scoped. - Reserve and verify the names. Document that the maintainers control both PyPI and npm names, and record where they are registered.
- Fix the repository URL in
setup.pyto the real location so consumers can verify provenance. - Pin the source of truth in CI. Add a check that the generated
package.json/setup.pyname matches an expected value, failing the build on drift. - Consider provenance attestation — npm and PyPI both support it, and it gives consumers a cryptographic statement about where the artefact came from.
- Add integrity pinning for install sources:
.npmrcwith a registry URL and, where practical, lockfile integrity verification (already in place vianpm ci).
Constraints
- Renaming a published package is breaking for existing consumers. Coordinate with maintainers and check whether the current names have been published at all — if they are new and unused, renaming now is cheap.
package.jsonhas"private": true, so the root package cannot be published accidentally — that protection must be preserved.- Do not add publishing credentials to the repository; use CI secrets or npm provenance.
- The Python SDK version is passed as
${{ github.ref_name }}in CI, which produces invalid PEP 440 versions for branch names likefeature/x. That is a separate publishing bug worth flagging.
Acceptance Criteria
- Every publishable artifact name is scoped and documented.
- The Python SDK
setup.pyURL points at the real repository. - CI verifies the generated package name matches an expected value and fails on drift.
- The root
package.jsonretains"private": true. - Publishing credentials are not present in the repository.
- Provenance/attestation is enabled or explicitly deferred with a reason.
- Dominant language
- TypeScript
- Stars
- 7
- Forks
- 55
- Avg merge
- 1d 17h
- Merged PRs (30d)
- 5
Getting set up
- Ships a Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from SourceXXL/alian_structure-api
-
good first issue help wanted security
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
SourceXXL/alian_structure-api#266 ·
-
Parallelize the cache-warming loop in `cache-warming.service.ts` — warmers run strictly sequentiallyPossibly taken @syntaxsuuvam-spec claimed this 2 days ago. Opengood first issue performance
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
SourceXXL/alian_structure-api#240 ·
-
documentation help wanted intermediate refactor
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
SourceXXL/alian_structure-api#215 ·
-
good first issue refactor tooling
Difficulty 2/5 1-3 hours Newbie friendliness 80/100
SourceXXL/alian_structure-api#199 ·
-
help wanted intermediate refactor
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
SourceXXL/alian_structure-api#196 ·
All issues in SourceXXL/alian_structure-api
Similar issues
-
A hung CI job runs for 6 hours before it is cancelledPossibly taken @Olanetsoft claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Olanetsoft/agent-lookout#110 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 90/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
thedotmack/claude-mem#4757 ·
Maintainers usually reply within 1 day
-
🐛 bug 🗺️ MCP OAuth
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
LibreChat-AI/LibreChat#17077 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 75/100