Skip to content

sync: mirror from thyn-ai/codna@54ade165c1e980a585b5e828e910c9d9cdecea23 - #76

Closed
0xamlab wants to merge 1 commit into
mainfrom
sync/54ade165c1e980a585b5e828e910c9d9cdecea23
Closed

0xamlab wants to merge 1 commit into
mainfrom
sync/54ade165c1e980a585b5e828e910c9d9cdecea23

Conversation

@0xamlab

@0xamlab 0xamlab commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

Automated mirror of cli/ (flattened), the root allowlist (server.json, glama.json, LICENSE, .gitleaks.toml) and the public-root/ community tree from thyn-ai/codna at 54ade165c1e980a585b5e828e910c9d9cdecea23. Merges itself via auto-merge once the mirror's required checks (codna review, Analyze (python)) pass and the codna-ai review approves; if a later sync lands first, this PR is closed as superseded -- every sync PR is a full snapshot of the exported surface.

@github-actions

github-actions Bot commented Nov 7, 2026

Copy link
Copy Markdown

Thanks for opening your first pull request in the Codna CLI! Please make sure the checks are green and that the change follows CONTRIBUTING.md. A maintainer will review it shortly.

@0xamlab

0xamlab commented Nov 7, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #77 (a later thyn-ai/codna commit). Every sync PR is a full snapshot of the exported surface, so this one carries nothing #77 does not. Closing.

@0xamlab 0xamlab closed this Nov 7, 2026
auto-merge was automatically disabled November 7, 2026 01:30

Pull request was closed

@0xamlab
0xamlab deleted the sync/54ade165c1e980a585b5e828e910c9d9cdecea23 branch November 7, 2026 01:30

@codna-ai codna-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

codna review — 2 finding(s): 2 inline, 0 in summary.

Reply @codna fix on a finding to have Codna open a verified, test-green, risk-gated fix PR.

⏸ Not approved: 2 medium/high finding(s) in this review.

try:
sys.exit(main())
except OverlayError as error:
print(json.dumps({"error": error.code, "message": error.message, **error.details}), file=sys.stderr)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 MEDIUM · correctness — OverlayError 'error' detail key silently overwrites error code in main outpu

Line 111 raises OverlayError("manifest_invalid", ..., error=str(exc)), storing error=str(exc) in self.details. At line 260 the dict literal {"error": error.code, "message": error.message, **error.details} is constructed: when error.details contains the key "error", Python dict unpacking silently overwrites the earlier "error": error.code entry with the detail value (the JSON decode error string). The CLI stderr output for a corrupt manifest would show the JSONDecodeError message as the "error" field instead of "manifest_invalid", making the error code unrecognisable by any consumer parsing that JSON.

Suggested change
print(json.dumps({"error": error.code, "message": error.message, **error.details}), file=sys.stderr)
Rename the detail kwarg at line 111 to avoid collision:
```python
raise OverlayError("manifest_invalid", f"{path} is not valid JSON", path=str(path), parse_error=str(exc)) from exc

Or build the JSON dict defensively:

payload = {"error": error.code, "message": error.message}
payload.update(error.details)
print(json.dumps(payload), file=sys.stderr)

_Reply `@codna fix` and Codna opens a verified, test-green, risk-gated fix PR._

<!-- codna:review:fp=e0b38b7367cb8b4f -->
<!-- codna:finding eyJmcCI6ICJlMGIzOGI3MzY3Y2I4YjRmIiwgInBhdGgiOiAibWVtZW5naW5lL19jb2RuYV9vdmVybGF5LnB5IiwgImxpbmUiOiAyNjAsICJlbmRfbGluZSI6IG51bGwsICJzZXZlcml0eSI6ICJtZWRpdW0iLCAiY2F0ZWdvcnkiOiAiY29ycmVjdG5lc3MiLCAidGl0bGUiOiAiT3ZlcmxheUVycm9yICdlcnJvcicgZGV0YWlsIGtleSBzaWxlbnRseSBvdmVyd3JpdGVzIGVycm9yIGNvZGUgaW4gX19tYWluX18gb3V0cHUiLCAiZXhwbGFuYXRpb24iOiAiTGluZSAxMTEgcmFpc2VzIGBPdmVybGF5RXJyb3IoXCJtYW5pZmVzdF9pbnZhbGlkXCIsIC4uLiwgZXJyb3I9c3RyKGV4YykpYCwgc3RvcmluZyBgZXJyb3I9c3RyKGV4YylgIGluIGBzZWxmLmRldGFpbHNgLiBBdCBsaW5lIDI2MCB0aGUgZGljdCBsaXRlcmFsIGB7XCJlcnJvclwiOiBlcnJvci5jb2RlLCBcIm1lc3NhZ2VcIjogZXJyb3IubWVzc2FnZSwgKiplcnJvci5kZXRhaWxzfWAgaXMgY29uc3RydWN0ZWQ6IHdoZW4gYGVycm9yLmRldGFpbHNgIGNvbnRhaW5zIHRoZSBrZXkgYFwiZXJyb3JcImAsIFB5dGhvbiBkaWN0IHVucGFja2luZyBzaWxlbnRseSBvdmVyd3JpdGVzIHRoZSBlYXJsaWVyIGBcImVycm9yXCI6IGVycm9yLmNvZGVgIGVudHJ5IHdpdGggdGhlIGRldGFpbCB2YWx1ZSAodGhlIEpTT04gZGVjb2RlIGVycm9yIHN0cmluZykuIFRoZSBDTEkgc3RkZXJyIG91dHB1dCBmb3IgYSBjb3JydXB0IG1hbmlmZXN0IHdvdWxkIHNob3cgdGhlIEpTT05EZWNvZGVFcnJvciBtZXNzYWdlIGFzIHRoZSBgXCJlcnJvclwiYCBmaWVsZCBpbnN0ZWFkIG9mIGBcIm1hbmlmZXN0X2ludmFsaWRcImAsIG1ha2luZyB0aGUgZXJyb3IgY29kZSB1bnJlY29nbmlzYWJsZSBieSBhbnkgY29uc3VtZXIgcGFyc2luZyB0aGF0IEpTT04uIn0= -->

Comment on lines +139 to +151
overlaid = manifest.get("overlaid_modules", [])
_require(isinstance(overlaid, list), "manifest_invalid", f"{path}: 'overlaid_modules' must be a list")
for entry in overlaid:
_require(
isinstance(entry, dict)
and isinstance(entry.get("path"), str)
and isinstance(entry.get("symbols"), list)
and bool(entry["symbols"]),
"manifest_invalid",
f"{path}: every 'overlaid_modules' entry needs a 'path' and a non-empty 'symbols' list",
path=str(path),
)
return manifest

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 MEDIUM · security — overlaid_modules paths not confined: missing_symbols can read files outside the

load_manifest calls require_confined_entry for every entry in preserve, rejecting ../ escapes and absolute paths. But overlaid_modules entries are only type-checked (must be a str), not path-confined. missing_symbols (line 218) then does base / module.path and reads the file for AST parsing without any confinement check. A malicious or accidentally malformed manifest entry such as {"path": "../../secrets.py", "symbols": ["x"]} would cause the tool to read and parse an arbitrary file outside the package. The same code that guards preserve entries should guard overlaid_modules entries.

Suggested change
overlaid = manifest.get("overlaid_modules", [])
_require(isinstance(overlaid, list), "manifest_invalid", f"{path}: 'overlaid_modules' must be a list")
for entry in overlaid:
_require(
isinstance(entry, dict)
and isinstance(entry.get("path"), str)
and isinstance(entry.get("symbols"), list)
and bool(entry["symbols"]),
"manifest_invalid",
f"{path}: every 'overlaid_modules' entry needs a 'path' and a non-empty 'symbols' list",
path=str(path),
)
return manifest
Add `require_confined_entry(entry["path"], base, path)` inside the loop at line 141, after the existing `_require` check.

Reply @codna fix and Codna opens a verified, test-green, risk-gated fix PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant