@clear-capabilities/agentic-security-scanner 0.154.0 → 0.156.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/bin/agentic-security.js +8 -0
- package/dist/1919.index.js +445 -0
- package/dist/2862.index.js +2 -2
- package/dist/8551.index.js +47 -19
- package/dist/8798.index.js +4 -2
- package/dist/agentic-security.mjs +4 -4
- package/dist/agentic-security.mjs.sha256 +1 -1
- package/package.json +6 -4
- package/src/engine.js +2 -2
- package/src/language/assurance.js +2 -2
- package/src/language/haskell-guards.js +12 -5
- package/src/language/haskell-ir.js +8 -1
- package/src/language/haskell-models.js +8 -0
- package/src/language/haskell-security-rules.js +23 -2
- package/src/language/haskell-supply.js +6 -6
- package/src/language/haskell-web.js +3 -0
- package/src/language/nix-secrets.js +2 -0
- package/src/language/nixos-hardening.js +32 -1
- package/src/language/resolved-pass.js +45 -17
- package/src/language/support-registry.js +70 -1
- package/src/language/trusted-inputs.js +38 -0
- package/src/language/witness.js +4 -2
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Where an advisory snapshot may come from (trust boundary).
|
|
2
|
+
//
|
|
3
|
+
// An advisory snapshot decides which dependencies are reported as vulnerable. A scanned project is untrusted input: if the project could
|
|
4
|
+
// supply its own snapshot, a pull request could ship an empty, perfectly well-formed, freshly dated one and the scan would report
|
|
5
|
+
// "complete" with the vulnerable dependency gone. So a snapshot is accepted only from the operator:
|
|
6
|
+
// 1. the environment variable named by the caller (a path the operator set), or
|
|
7
|
+
// 2. a file in the operator's per-user configuration directory ($XDG_CONFIG_HOME/agentic-security, or ~/.config/agentic-security),
|
|
8
|
+
// the same directory that holds the per-install signing key.
|
|
9
|
+
// A file of the same name inside the scanned project is never read. It is reported, so the operator knows why it had no effect.
|
|
10
|
+
|
|
11
|
+
import { existsSync, lstatSync } from 'node:fs';
|
|
12
|
+
import { homedir } from 'node:os';
|
|
13
|
+
import { join } from 'node:path';
|
|
14
|
+
import { statePath } from '../posture/state-dir.js';
|
|
15
|
+
|
|
16
|
+
/** The operator's per-user configuration directory. */
|
|
17
|
+
export function operatorConfigDir(env = process.env) {
|
|
18
|
+
const base = env.XDG_CONFIG_HOME && env.XDG_CONFIG_HOME.length ? env.XDG_CONFIG_HOME : join(homedir(), '.config');
|
|
19
|
+
return join(base, 'agentic-security');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const isRegularFile = (p) => { try { return lstatSync(p).isFile(); } catch { return false; } };
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Resolves a snapshot path from operator-controlled places only.
|
|
26
|
+
* @returns {{path: string|null, source: 'env'|'operator-config'|null, projectLocalIgnored: string|null}}
|
|
27
|
+
*/
|
|
28
|
+
export function resolveOperatorSnapshot({ envVar, fileName, root = null, env = process.env }) {
|
|
29
|
+
const local = root ? statePath(root, fileName) : null;
|
|
30
|
+
const projectLocalIgnored = local && existsSync(local) ? local : null;
|
|
31
|
+
if (env[envVar]) return { path: env[envVar], source: 'env', projectLocalIgnored };
|
|
32
|
+
const cfg = join(operatorConfigDir(env), fileName);
|
|
33
|
+
if (isRegularFile(cfg)) return { path: cfg, source: 'operator-config', projectLocalIgnored };
|
|
34
|
+
return { path: null, source: null, projectLocalIgnored };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** The sentence added to a "no snapshot" reason when the project carried one that was deliberately ignored. */
|
|
38
|
+
export const IGNORED_NOTE = (fileName) => ` A ${fileName} inside the scanned project was IGNORED: a project cannot vouch for its own advisories (provide the snapshot through the environment variable or your per-user configuration directory).`;
|
package/src/language/witness.js
CHANGED
|
@@ -146,8 +146,10 @@ export function judgeFixWitness(before, after) {
|
|
|
146
146
|
export function haskellRunner() {
|
|
147
147
|
const p = which('runghc') || which('runhaskell');
|
|
148
148
|
if (!p) return { available: false, reason: 'no Haskell toolchain (runghc) on PATH; witnesses for Haskell findings are unavailable here' };
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
// GHC's first start on a cold, loaded machine (a CI runner) has taken more than 10 s; a probe that gives up there reports a toolchain
|
|
150
|
+
// that is installed as absent, and the answer then differs between two calls in one run.
|
|
151
|
+
const v = spawnSync(p, ['--version'], { encoding: 'utf8', timeout: 60_000 });
|
|
152
|
+
return v.status === 0 ? { available: true, path: p, version: String(v.stdout || v.stderr).trim() } : { available: false, reason: v.error && v.error.code === 'ETIMEDOUT' ? 'the Haskell runner did not start within 60 s' : 'the Haskell runner did not start' };
|
|
151
153
|
}
|
|
152
154
|
|
|
153
155
|
/**
|