Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
35 changes: 34 additions & 1 deletion .github/osv-scanner-lockfiles.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
{
"description": "Every tracked dependency lockfile or manifest that security-scan.yml's osv-scanner job scans. A lockfile entry without a parser lets OSV-Scanner infer it from the file name; parser names the OSV-Scanner v2 extractor for names it cannot infer (--lockfile=<parser>:<path>). A covered_by_lockfile entry is a manifest OSV-Scanner v2.6.0 has no source extractor for; its sibling lockfile is scanned instead. An excluded entry is a tracked lockfile deliberately left out of the scan; it needs a reason and an evidence path, and only a deliberately vulnerable test fixture qualifies. A lockfile entry that names a config is scanned in an invocation of its own under that config alone (an explicit --config applies to every input of one invocation), and every other entry together under .github/osv-scanner.toml; the tests bind each such config to its one lock. tests/test_osv_lockfile_coverage.py fails when a tracked lockfile or manifest is in none of the three lists.",
"description": "Every tracked dependency lockfile or manifest that security-scan.yml's osv-scanner job scans. A lockfile entry without a parser lets OSV-Scanner infer it from the file name; parser names the OSV-Scanner v2 extractor for names it cannot infer (--lockfile=<parser>:<path>). A covered_by_lockfile entry is a manifest OSV-Scanner v2.6.0 has no source extractor for; its sibling lockfile is scanned instead. An excluded entry is a tracked lockfile deliberately left out of the scan; it needs a reason and an evidence path. Permitted exclusions are deliberately vulnerable test fixtures and captured native resolver or probe inputs retained with original hash/command evidence that no shipped installation recipe consumes. Captured inputs may retain unused platform or historical dependency branches; they do not qualify a runtime or grant an advisory exception. Every active installation lock and frozen application lock remains scanned. A lockfile entry that names a config is scanned in an invocation of its own under that config alone (an explicit --config applies to every input of one invocation), and every other entry together under .github/osv-scanner.toml; the tests bind each such config to its one lock. tests/test_osv_lockfile_coverage.py fails when a tracked lockfile or manifest is in none of the three lists.",
"lockfiles": [
{"path": "blueprints/runtime-workers/crawl4ai/requirements.lock", "parser": "requirements.txt"},
{"path": "blueprints/runtime-workers/crawl4ai/test-requirements.lock", "parser": "requirements.txt"},
{"path": "blueprints/runtime-workers/crawl4ai/grader/package-lock.json"},
{"path": "blueprints/runtime-workers/gpt-researcher/requirements.lock", "parser": "requirements.txt"},
{"path": "blueprints/runtime-workers/gpt-researcher/build-requirements.lock", "parser": "requirements.txt"},
{"path": "blueprints/runtime-workers/gpt-researcher/proxy-requirements.lock", "parser": "requirements.txt"},
{"path": "blueprints/runtime-workers/deerflow/e2e/requirements.lock", "parser": "requirements.txt"},
{
"path": ".github/requirements-ci.txt",
"parser": "requirements.txt"
Expand Down Expand Up @@ -172,6 +179,12 @@
}
],
"covered_by_lockfile": [
{"path": "blueprints/runtime-workers/crawl4ai/requirements.in", "lockfile": "blueprints/runtime-workers/crawl4ai/requirements.lock"},
{"path": "blueprints/runtime-workers/crawl4ai/grader/package.json", "lockfile": "blueprints/runtime-workers/crawl4ai/grader/package-lock.json"},
{"path": "blueprints/runtime-workers/gpt-researcher/requirements.in", "lockfile": "blueprints/runtime-workers/gpt-researcher/requirements.lock"},
{"path": "blueprints/runtime-workers/gpt-researcher/build-requirements.in", "lockfile": "blueprints/runtime-workers/gpt-researcher/build-requirements.lock"},
{"path": "blueprints/runtime-workers/gpt-researcher/proxy-requirements.in", "lockfile": "blueprints/runtime-workers/gpt-researcher/proxy-requirements.lock"},
{"path": "blueprints/runtime-workers/deerflow/e2e/requirements.txt", "lockfile": "blueprints/runtime-workers/deerflow/e2e/requirements.lock"},
{
"path": "blueprints/convergence-practice/application-delivery/package.json",
"lockfile": "blueprints/convergence-practice/application-delivery/pnpm-lock.yaml"
Expand Down Expand Up @@ -210,6 +223,26 @@
}
],
"excluded": [
{
"path": "blueprints/runtime-workers/openhands/evidence/pyjwt-relock-20260930-constraints.txt",
"reason": "Frozen native compile-input reproducibility fixture for the PyJWT 2.15.0 relock, retaining original bytes, command and target-specific selection in its receipt. It includes unused platform branches and is not an installable runtime closure. No recipe installer consumes it. The selected Linux x86_64/CPython 3.13.15 closure remains blueprints/runtime-workers/openhands/requirements.lock, which is natively scanned and SHA-bound by the ignore guard. Active runtime locks remain scanned; this fixture exclusion grants no advisory ignore or runtime acceptance.",
"evidence": "blueprints/runtime-workers/openhands/evidence/pyjwt-relock-20260930.json"
},
{
"path": "blueprints/runtime-workers/openhands/evidence/urllib3-relock-20260930-constraints.txt",
"reason": "Frozen native compile-input reproducibility fixture for the intermediate urllib3 2.8.0 relock, retaining original bytes, command and target-specific selection in its receipt. It includes unused platform branches and is not an installable runtime closure. No recipe installer consumes it. The selected Linux x86_64/CPython 3.13.15 closure remains blueprints/runtime-workers/openhands/requirements.lock, which is natively scanned and SHA-bound by the ignore guard. Active runtime locks remain scanned; this fixture exclusion grants no advisory ignore or runtime acceptance.",
"evidence": "blueprints/runtime-workers/openhands/evidence/urllib3-relock-20260930.json"
},
{
"path": "blueprints/runtime-workers/openhands/evidence/main-reconcile-20260930-constraints.txt",
"reason": "Frozen native compile-input reproducibility fixture copied from the reviewed main lock, with original bytes, baseline SHA, command and target-specific selection retained in the reconciliation receipt. It includes unused platform branches and is not an installable runtime closure. No recipe installer consumes this captured evidence fixture. The selected Linux x86_64/CPython 3.13.15 closure remains blueprints/runtime-workers/openhands/requirements.lock, which is natively scanned and SHA-bound by the independent ignore guard. All nine active runtime install locks remain scanned; this fixture exclusion grants no advisory ignore or runtime acceptance.",
"evidence": "blueprints/runtime-workers/openhands/evidence/main-reconcile-20260930-commands.json"
},
{
"path": "blueprints/runtime-workers/openhands/evidence/wheel-relock-20260930-constraints.txt",
"reason": "Frozen native compile-input reproducibility fixture, retained with its original hash and command in the relock receipt. It constrains the qualification resolver and includes unused Windows/macOS branches from the prior multi-platform export; it is not an installable runtime closure. No recipe installer consumes this captured evidence fixture. The selected Linux/Python 3.13.15 closure is blueprints/runtime-workers/openhands/requirements.lock, whose exact bytes are natively scanned and SHA-bound by the independent ignore guard. Both active OpenHands install locks and every other runtime install lock remain scanned; this exclusion grants no advisory ignore or runtime acceptance.",
"evidence": "blueprints/runtime-workers/openhands/evidence/wheel-relock-20260930.json"
},
{
"path": "evidence/artifacts/gap-wave2-20260923/us-equities__identity-provenance/raw/dvc-fixround3/repo-git__dvc.lock",
"reason": "Gap-wave-2 captured evidence fixture for layer us-equities__identity-provenance (catalog PR: gap-wave2 agent-lab-17): the dependency list a gap check installed into an isolated cache prefix, or a copy of a probe repository's lock, retained so the receipt is reproducible. Nothing in the catalog installs it, and scanning it would report advisories for a probe environment rather than for a shipped dependency.",
Expand Down
5 changes: 5 additions & 0 deletions .github/osv-scanner.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
# that still lists that advisory.
[[IgnoredVulns]]
id = "GHSA-8mgp-746c-j5xp"
# 2026-09-30: the GPT Researcher and Crawl4AI source-only allowances are bound
# to exact locks in IGNORE_ALLOWED_LOCKS and independently rechecked in
# evidence/artifacts/runtime-roster-20260930/lock-scan-and-nltk-scope.json.
# No new ignored advisory or expiry extension; dynamic/model-artifact paths
# and broader worker activation remain outside this bounded source review.
ignoreUntil = 2026-12-24
reason = "nltk through 3.10.3: TransitionParser.train/parse, AveragedPerceptron.save/load, PerceptronTagger.save_to_json and nltk.classify.maxent.save_maxent_params open caller-chosen model paths with the built-in open() instead of the pathsec helpers (the advisory's comparison case is the guarded PerceptronTagger.load_from_json, which in 3.10.3 still authorizes a caller-chosen private model directory), so untrusted input that chooses a model import or export path can read or write outside the allowed roots; pathsec enforcement is on by default (ENFORCE = True in nltk/pathsec.py of 3.10.3). No patched release as of 2026-09-27; the fixes are merged on develop (nltk #3757, #3759, #3813). Each lock allowed to pin nltk is named, with its reviewed sha256 and non-reachability evidence, in IGNORE_ALLOWED_LOCKS in tests/test_osv_lockfile_coverage.py. Lumibot lock: nltk 3.10.3 is a transitive pin (google-adk, llama-index-core) of the evaluation-only Lumibot 4.6.1 environment, run offline under bwrap, and no trial code calls these APIs (evidence: blueprints/us-equities/engine-trials/spy-one-zero-20260926/repository-checks.json). Expiry plan: relock every allowed lock onto the first nltk release that ships those fixes, then delete this ignore; delete the Lumibot lock unless a verdict has adopted Lumibot."

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Planned native browser-image qualification

This is a source-backed experiment plan, with no observations or adoption.
It follows the repository's [convergence contract](../contract-reference.md)
and preserves the existing full-image, observer and task-quality gates.

## Pinned source and comparison

Use OpenHands software-agent-sdk v1.50.0 at
`dcf401af7a9a302ef92cb7d092e1df9bb659daa5` and its unchanged
[native builder](https://github.com/OpenHands/software-agent-sdk/blob/dcf401af7a9a302ef92cb7d092e1df9bb659daa5/openhands-agent-server/openhands/agent_server/docker/build.py)
and [Dockerfile](https://github.com/OpenHands/software-agent-sdk/blob/dcf401af7a9a302ef92cb7d092e1df9bb659daa5/openhands-agent-server/openhands/agent_server/docker/Dockerfile).
The baseline is the published full image at digest
`sha256:6d91a74fd2b556107e4e15476680d1d8116eeadfc06879baf7193caa73314dfc`.
The candidate uses the builder's supported browser capability selection.
It removes the optional OpenVSCode and nested-Docker packages; retaining
Chromium and the full stage's GitHub CLI is source composition evidence.
Preservation of the selected terminal, file-editor, planner, browser and
delegation tools still needs native execution. The upstream `minimal`
composition omits browser and GitHub CLI and does not meet this plan's contract.

The [retained image triage](../../runtime-workers/openhands/evidence/image-triage-20260930.json)
records native scan exit 0 with 56 fixable high/critical matches; its command
generated a report without a severity threshold. Those findings leave image
acceptance pending. A native manifest read on September 30 returned the same
published digest. Historical findings remain historical; this plan does not
turn that identity check into a passing fresh scan. Source review corrected
the initial shorthand "failed scan" to distinguish native command exit from
the unmet acceptance rule.

The Dockerfile pins system CPython 3.13.15 and separately copies a managed
3.13 interpreter. A base-image override alone does not repair both copies.
The [CPython backport](https://github.com/python/cpython/pull/157192)
is at `b8f23e307097552eaea2604383a12ab280520d0d`; the
[3.13 release schedule](https://github.com/python/peps/blob/main/peps/pep-0719.rst)
places 3.13.16 on October 6. A scheduled release is not an available remedy
or acceptance evidence. The candidate can therefore still fail the threshold.

## Execution boundary and native commands

Before execution, the coordinator and the active measurement owner settle the
host-resource boundary and record native container/build prerequisites,
available disk and memory, selected base/snapshot identities and the owned
cleanup path. Perform one model-free build in an isolated source checkout and
existing rootless container context, using a verified Linux/amd64 builder.
The native `--arch` flag labels tags; the local `--load` path does not pass
`--platform` to Buildx. Do not change a shared gateway, account, launcher,
global setting, deployed Collector or measurement window. No build, pull,
service launch or model qualification is performed by this plan.

From the pinned SDK source, the supported proposed commands are:

```sh
rtk uv run --frozen python -m openhands.agent_server.docker.build --base-image python-node-runtime --image localhost/nas-openhands-trial --image-flavor default --target binary --custom-tags v1.50.0-browser --install-capabilities browser --install-acp-providers claude-code,codex,gemini-cli --arch amd64 --load
rtk grype docker:localhost/nas-openhands-trial:dcf401a-v1.50.0-browser-amd64 --platform linux/amd64 --only-fixed --fail-on high --output json
rtk docker run --rm --platform linux/amd64 localhost/nas-openhands-trial:dcf401a-v1.50.0-browser-amd64 --check-browser
```

Correction during source review: `--custom-tags` takes a suffix, so the bare
`:v1.50.0-browser` target first proposed in research was wrong. Native
`BuildOptions.all_tags` evaluation returned exit 0 and the corrected tag
above, following [the pinned derivation](https://github.com/OpenHands/software-agent-sdk/blob/dcf401af7a9a302ef92cb7d092e1df9bb659daa5/openhands-agent-server/openhands/agent_server/docker/build.py#L581).
The image's native `--check-browser` renders `about:blank`, closes its
executor and exits 0 or 1 before server startup, following
[the pinned check](https://github.com/OpenHands/software-agent-sdk/blob/dcf401af7a9a302ef92cb7d092e1df9bb659daa5/openhands-agent-server/openhands/agent_server/__main__.py#L138).
No browser or model execution is claimed by this source check.

Use Grype 0.119.0, preserving the actual JSON and exit status. Its native
threshold failure is exit 2. Retain the candidate image identity, SBOM/database
identity and every attempt, including a failed build or scan. A passing scan
requires zero fixable high/critical findings under the exact recorded native
command; removing one optional package is insufficient.

## Predeclared quality and usage rules

A scan pass and native browser check are necessary for this image trial.
The selected tools must retain their installed native contracts and no tool
may be declared preserved from dependency metadata alone. The image remains
a candidate until these checks and recovery/cleanup evidence are retained.
This plan does not accept a provider route, whole-task quality, independent
observer, Gate A/P3 or a token-saving comparison.

Future task qualification uses the maintained
[OpenHands benchmarks](https://github.com/OpenHands/benchmarks/tree/405bae7140d7e961a75f4910a0b2e7069731db96)
and its native SWE-bench/GAIA evaluation paths. That revision pins SDK
`43376f1868ffd702746080714a59c16d3f69ec12`, so compatibility with v1.50.0
must be qualified before using it. Freeze instance IDs, dataset identities,
an explicit route and one worker with a 12-iteration cap. The GAIA
`question_scorer` is the native grading path; aggregating stored scores is
not a new grading run. Dataset access and native prerequisites stay separate
from this model-free image trial. No credential is fetched for this plan.

Laminar telemetry inside an agent process does not independently observe that
process. A future observer must have separate host ownership and controls.
[Tetragon process lifecycle](https://tetragon.io/docs/use-cases/process-lifecycle/)
is a research lead with Linux BTF/privilege prerequisites, not a selected or
installed service and not an oracle for model quality, skills or token use.

All provider and whole-task usage remains unknown. Model-free execution may
record observed native usage separately; no missing field becomes zero and
no historical cumulative receipt is added twice. Do not publish savings from
this plan. Roll back by retaining the current selection and removing only the
trial's owned image/build artifacts under the native lifecycle.

The pinned repository is MIT-licensed, and the SDK/tools/server declare
Python >=3.12. Third-party image contents retain their own licenses and
runtime compatibility requirements; this source review does not qualify
them collectively.
Loading
Loading