mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-13 10:43:43 +03:00
Compare commits
3 Commits
fix/audio-
...
fix/securi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9819343d1 | ||
|
|
e8245f6b63 | ||
|
|
266ffc9756 |
@@ -72,7 +72,7 @@ export class TinyCmsExecutor extends BaseExecutor {
|
||||
// Security context: this nonce is signed into `x-secure-signature` and
|
||||
// reused as the session id, so it must be unpredictable. `node:crypto`
|
||||
// randomUUID() is always available on the supported runtime — never fall
|
||||
// back to Math.random() (CodeQL js/insecure-randomness).
|
||||
// back to a non-CSPRNG source (CodeQL js/insecure-randomness).
|
||||
const nonceJs = randomUUID();
|
||||
|
||||
const securePayload = generateSecurePayload(
|
||||
|
||||
57
tests/unit/security-alerts-0812.test.ts
Normal file
57
tests/unit/security-alerts-0812.test.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import test from "node:test";
|
||||
|
||||
const REPO_ROOT = join(import.meta.dirname, "..", "..");
|
||||
|
||||
/**
|
||||
* Regression guards for the CodeQL alerts triaged on 2026-08-12.
|
||||
*
|
||||
* Both are source-level invariants rather than behavioral round-trips: the functions they
|
||||
* protect are module-private (`decodeXmlText`) or only reachable through a live upstream
|
||||
* handshake (`tinycms` nonce), so the guard asserts the property on the source itself.
|
||||
*/
|
||||
|
||||
test("decodeXmlText decodes & last so encoded entities do not double-unescape", () => {
|
||||
const source = readFileSync(
|
||||
join(REPO_ROOT, "open-sse/vendor/codex-chatgpt-web/adapters/chatgpt-web/environment.ts"),
|
||||
"utf8"
|
||||
);
|
||||
const body = /function decodeXmlText\(value: string\): string \{([\s\S]*?)\n\}/.exec(source)?.[1];
|
||||
assert.ok(body, "decodeXmlText not found — update this guard if the helper was renamed");
|
||||
|
||||
const order = [...body.matchAll(/replaceAll\("(&[^"]+;)"/g)].map((match) => match[1]);
|
||||
assert.ok(order.length >= 2, `expected several entity replacements, got ${order.length}`);
|
||||
assert.equal(
|
||||
order.at(-1),
|
||||
"&",
|
||||
`"&" must be the LAST entity decoded, otherwise """ decodes to '"' instead ` +
|
||||
`of the literal """. Current order: ${order.join(" -> ")}`
|
||||
);
|
||||
|
||||
// Mirror the implementation to document the property the ordering buys us.
|
||||
const decode = (value: string) =>
|
||||
order.reduce((acc, entity) => {
|
||||
const plain = { "<": "<", ">": ">", """: '"', "'": "'", "&": "&" }[entity];
|
||||
return plain === undefined ? acc : acc.replaceAll(entity, plain);
|
||||
}, value);
|
||||
assert.equal(decode("&quot;"), """);
|
||||
assert.equal(decode("&#39;"), "'");
|
||||
assert.equal(decode("&lt;"), "<");
|
||||
});
|
||||
|
||||
test("tinycms signs its anti-replay nonce with a CSPRNG, never Math.random", () => {
|
||||
const source = readFileSync(join(REPO_ROOT, "open-sse/executors/tinycms.ts"), "utf8");
|
||||
|
||||
assert.match(
|
||||
source,
|
||||
/const nonceJs = randomUUID\(\)/,
|
||||
"the tinycms nonce must come from node:crypto randomUUID"
|
||||
);
|
||||
assert.doesNotMatch(
|
||||
source,
|
||||
/Math\.random\(\)/,
|
||||
"Math.random() is not a CSPRNG — the nonce is signed into the anti-replay payload"
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user