2026-04-16 13:48:04 +08:00
# Security Policy
## Supported versions
Only the latest release on the `main` branch receives security fixes.
| Version | Supported |
|---------|-----------|
| Latest (`main` ) | Yes |
| Older releases | No |
## Reporting a vulnerability
If you find a security issue (e.g. prompt injection, credential exposure, unintended data exfiltration through API calls), **do not open a public issue ** .
Instead, use GitHub's **private vulnerability reporting ** :
1. Go to the [Security Advisories ](https://github.com/Imbad0202/academic-research-skills/security/advisories ) page.
2. Click * * "Report a vulnerability"**.
3. Fill in the details — what you found, how to reproduce it, and the potential impact.
docs: solo-maintainer governance statement + SECURITY triage procedure (#760) (#778)
* docs: solo-maintainer governance statement + SECURITY triage procedure (#760)
GOVERNANCE.md: decision authority, honest cross-model scope
(error-detection control, not organizational independence), release
authority, EOL posture, and the operating-principles section (three
distilled principles with informative ISO/IEC 42001 anchors, the
#753-#760 coverage map, Annex C not-applicable assessments).
SECURITY.md: 7-day promise becomes acknowledgement-only hard promise
plus a written severity-tiered best-effort triage procedure.
NOTICE.md: governance pointer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AFJbYZyrJmSPFMJKQZhVHC
* docs: apply dual-agent review to #760 (order-safe claims, honest ceilings, sustainable promises)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AFJbYZyrJmSPFMJKQZhVHC
* docs: close codex R1 on #760 (per-operator cross-model attribution, fairness signals disclosed, EOL-scoped promises)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AFJbYZyrJmSPFMJKQZhVHC
* docs: narrow fairness scoring absolute to persons/real-world allocation (codex R2)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AFJbYZyrJmSPFMJKQZhVHC
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 10:57:38 +08:00
You will receive an acknowledgement within 7 days. What happens after that follows the triage procedure below.
## Triage and response procedure
This project is solo-maintained ([GOVERNANCE.md ](GOVERNANCE.md )). The 7-day acknowledgement above is the only hard time-bound promise; the fix targets below are best-effort, stated so they can be held to honestly. These promises hold while the project is actively maintained — on end-of-life (GOVERNANCE.md § Continuity and end of life) they lapse with the rest of maintenance.
1. **Acknowledgement ** — within 7 days of the report: confirmation it arrived and, where possible, a first read on whether it is in scope.
2. **Severity classification ** — each in-scope report is classified:
| Severity | Definition | Response |
|---|---|---|
| **Critical ** | Exploitable on a default install path: credential exposure, or data leaving the machine beyond the [docs/DATA_FLOWS.md ](docs/DATA_FLOWS.md ) map | Best-effort target 14 days; GitHub security advisory published with the fix |
| **High ** | Integrity-gate bypass or prompt injection that reaches gate decisions on a default path | Fix in the next release; best-effort target 30 days; advisory published with the fix |
| **Moderate / Low ** | Hardening of opt-in paths, defense-in-depth, issues requiring unusual configuration | Scheduled into ordinary release work; no target date promised |
3. **Resolution ** — accepted reports get a fix on `main` and credit in the release notes (say so if you prefer no credit). Declined reports get a written explanation.
4. **Coordinated disclosure ** — please hold exploit details until a fix is released; a GitHub security advisory is published for Critical and High fixes. You are welcome to ask for a status update in the same private thread at any time.
2026-04-16 13:48:04 +08:00
## Scope
The following are in scope for security reports:
- **Prompt injection** — inputs that cause agents to bypass IRON RULE constraints, integrity gates, or ethics protocols
- **Credential leakage** — configurations or agent behaviors that expose API keys (`ARS_CROSS_MODEL` , Semantic Scholar API key, etc.)
docs: DATA_FLOWS.md — single map of network touchpoints + local stores (#758) (#770)
* docs: single data-flow map + DF-1..DF-3 coverage lint (#758)
Add docs/DATA_FLOWS.md — one row per network touchpoint (trigger,
payload class, recipient, credentials, off switch) and one row per
local store (path, content, TTL, deletion), with an explicit scope
statement (the Claude session itself is platform-governed; nothing
publishes autonomously). Covers the four gate resolvers, the
standalone Chinese-literature resolver (NOT in the gate), the
consent-bound claim-standing discovery adapters, both cross-model
transports (API and citation-only Codex subscription), the SessionStart
update check, the manual smoke tests, and the v3.9.4 timeline
bootstrap — the last one surfaced by the new lint itself on first run
(it was absent from the #758 issue enumeration).
Inbound links from README, SECURITY.md (in-scope exfiltration anchor),
and THIRD_PARTY.md (core-suite vs third-party contrast).
Lint (same-PR drift-point discipline): scripts/check_data_flows.py —
DF-1 every non-test scripts/*.py importing a network module (AST scan,
so no-call guards naming urllib.request in strings do not count) must
be named on the map; DF-2 same for curl-invoking shell scripts; DF-3
README/SECURITY/THIRD_PARTY keep a rendered resolving inbound link
(fences + HTML comments stripped with the semantics converged in the
PR #768 review; consolidation into a shared helper is follow-up).
12 mutation tests; wired into spec-consistency.yml + pytest manifest.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc
* refactor: apply /simplify pass (4-agent, deduped) (#758)
Doc: the four gate resolvers collapse into a 4-column sub-table under
one shared trigger/payload/off-switch lead (the wide table kept only
heterogeneous touchpoints); the exhaustiveness sentence is bounded to
what DF-1/DF-2 actually detect (direct imports + curl; spawned-CLI and
session-tooling paths held by review); "Nothing here publishes" now
inherits POSITIONING.md and its not-a-runtime-guarantee qualifier; the
subscription-free note is trimmed to its rationale; Related gains the
SETUP bullet as the tunables authority.
Coverage: docs/SETUP.md becomes the fourth DF-3-pinned inbound surface
(pointer added in the cache section); the four translated READMEs
mirror the README pointer; docs/DATA_FLOWS.md registers into
check_spec_consistency.py relative-link validation.
Lint: DF-1 module vocabulary rebuilt as the network subset of the
no-call envelope FORBIDDEN_IMPORTS (deviations documented: dotted
urllib.request/http.client instead of bare urllib/http; ssl excluded);
scan is now recursive into scripts/ subpackages. Tunable constants in
verification_cache.py gain update-both comments.
Tests: the three hollow assert-baseline tests become real mutations
(name-based test exemption, uncomment-curl, from-urllib idiom);
recursive-scan and SETUP-surface tests added (17 total).
Skipped with reason: endpoint-hostname lint (near-zero event rate,
composed-URL false-fire risk); row-id shrink constant (review-owned per
degradation-registry precedent); markdown-helper consolidation with
check_control_availability.py (whichever PR merges second extracts the
shared module — recorded in both PR bodies).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc
* fix: close codex R1 findings — 8 P2 + 4 P3 (#758)
Doc accuracy (6): Chinese-literature row rewritten (callable client, no
CLI; PubMed path sends the required NCBI contact email + bibliographic
search coordinates); codex-transport payload names citation_context
(can contain unpublished manuscript text); update check documented as
one curl transfer per 24 h with redirects and the
ARS_UPDATE_CHECK_REMOTE_URL override; retraction-status SQLite cache
added to local stores (caller-supplied path, 30-day stale threshold,
no auto-expiry); discovery adapters credentials corrected (fixed
User-Agent, resolver env keys not consumed); resolver payload narrowed
to identifiers + title query strings; update-check state content
corrected (state label + two version strings).
Lint mis-pass/mis-fire (4): DF-1/DF-2 coverage now requires the full
repo-relative path (basename-substring collision closed); DF-2 is
recursive over scripts/ and hooks/, recognizes path-qualified curl,
and masks quoted spans before the comment strip; DF-3 strips inline
code spans before link extraction (a backticked link does not render).
Five mutation tests added (22 total). The code-span rule is a
divergence from check_control_availability.py to be carried over at
the declared helper consolidation.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc
* fix: close codex R2 findings — 4 P2 + 1 P3 (#758)
- DF-2 scans command-substitution bodies BEFORE quote masking, so
resp="$(curl ...)" — a real network call inside double quotes — fires
(mutation test added; suite now genuinely 22, correcting the prior
commit message which said 22 when 21 were collected).
- Map gains the Codex audit wrapper row (scripts/run_codex_audit.sh:
human/CI/hook-invoked only, sends deliverable + supporting file
contents through the local Codex CLI login).
- Update check re-bounded: at most one SUCCESSFUL check per 24 h; a
failed attempt writes no state and may retry next session.
- Cache TTL wording corrected: expiry is a cache miss, not deletion;
expired rows persist until invalidated or the file is deleted.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc
* fix: full comment lines execute nothing — DF-2 substitution scan (#758)
The R2 command-substitution scan ran before any comment handling, so a
full comment line containing $(curl ...) false-fired — surfaced by the
codex R3 pass (timed out mid-review, but its transcript had already
demonstrated the false fire). Comment-only lines are now skipped before
the substitution scan; a $(curl) inside a trailing inline comment
remains a documented accepted edge. Mutation test added (23 total).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc
* fix: close codex R3 findings — command-position curl + image links + retention wording (#758)
- DF-2 rebuilt around COMMAND POSITION: curl counts only as the first
non-assignment token of a segment (pipes/separators/substitution
openers), so `command -v curl` preflights and `echo curl` no longer
false-fire; VAR=x curl still fires; wrapper-prefixed invocations
(sudo/timeout) are documented accepted edges.
- DF-3 link grammar excludes image syntax —  renders no
anchor and cannot keep the acceptance criterion green.
- Cache retention wording includes the overwrite path: expired rows
persist until overwritten by re-verification, invalidated, or the
file is deleted.
- Three mutation tests added (26 total).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc
* fix: close codex R4 finding — curl behind shell control words (#758)
The command-position head-token scan now skips shell control words
(if/elif/while/until/then/else/do/!/time/exec) before naming the head,
so `if curl …; then` and `while ! curl …; do` fire while `if true;
then` stays quiet. Two mutation tests (28 total).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc
* fix: close codex R5 finding — option tokens after control words (#758)
`time -p curl …` / option-bearing exec forms: the head scan now skips
`-`-prefixed option tokens alongside assignments and control words, so
the option cannot shadow the command head. Mutation test added (29
total).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc
* fix: close codex R6 finding — harness spawned-CLI paths scoped out (#758)
Three maintainer-only measurement scripts reach the network through
locally authenticated CLIs (dispatch_e4_panel via claude -p,
run_review_criteria_constructive_value via Codex, check_ranking_lift
via gh api). They are not user-facing feature paths, so instead of
diluting the touchpoint tables they are now an explicit named scope
exclusion — the exhaustiveness claim no longer silently spans them.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc
* fix: close codex R7 finding — boundary count wording (#758)
"Two boundaries" became three after the R6 harness exclusion; the count
is removed rather than maintained.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 00:28:24 +08:00
- **Data exfiltration** — agent behaviors that send user research data to unintended external services. The * intended * network touchpoints and local stores are mapped in [docs/DATA_FLOWS.md ](docs/DATA_FLOWS.md ); anything beyond that map is report-worthy.
2026-04-16 13:48:04 +08:00
- **Integrity gate bypass** — inputs that skip Stage 2.5 or Stage 4.5 blocking checks
The following are **out of scope ** :
- AI output quality issues (hallucinations, weak arguments) — these are research limitations, not security vulnerabilities
- Feature requests or general bugs — use [Issues ](https://github.com/Imbad0202/academic-research-skills/issues ) instead