Skip to content
Open
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions detailed_alerts_cowork.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"File Path","Line Number","Description","Link"
"src/electron/agent/executor.ts",12180,"Use of a broken or weak cryptographic algorithm","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/66"
"src/electron/gateway/security.ts",427,"Creating biased random numbers from a cryptographically secure source","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/65"
"src/electron/agent/tools/batch-image-tools.ts",353,"Shell command built from environment values","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/64"
"src/electron/memory/MemoryObservationService.ts",87,"Use of password hash with insufficient computational effort","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/63"
"src/electron/database/SecureSettingsRepository.ts",593,"Use of password hash with insufficient computational effort","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/62"
"src/electron/agent/tools/registry.ts",8374,"Use of password hash with insufficient computational effort","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/61"
"src/electron/agent/executor.ts",12180,"Use of password hash with insufficient computational effort","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/60"
"src/electron/agent/llm/prompt-cache.ts",186,"Use of password hash with insufficient computational effort","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/59"
"src/electron/agent/llm/prompt-cache.ts",154,"Use of password hash with insufficient computational effort","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/58"
"src/electron/hooks/server.ts",933,"Information exposure through a stack trace","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/57"
"src/electron/extensions/pack-registry.ts",93,"Incomplete URL substring sanitization","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/56"
"src/electron/extensions/pack-registry.ts",92,"Incomplete URL substring sanitization","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/55"
"src/electron/agent/tools/x-tools.ts",1143,"Incomplete URL substring sanitization","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/54"
"src/electron/agent/tools/x-tools.ts",1143,"Incomplete URL substring sanitization","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/53"
"src/electron/agent/tools/x-tools.ts",181,"Incomplete URL substring sanitization","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/52"
"src/electron/agent/tools/x-tools.ts",181,"Incomplete URL substring sanitization","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/51"
"src/electron/agent/tools/browser-tools.ts",1575,"Incomplete URL substring sanitization","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/50"
"src/electron/agent/tools/browser-tools.ts",1535,"Incomplete URL substring sanitization","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/49"
"src/electron/agent/skill-registry.ts",328,"Incomplete URL substring sanitization","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/48"
"src/electron/agent/skill-registry.ts",327,"Incomplete URL substring sanitization","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/47"
"scripts/collect-public-adoption-stats.mjs",68,"Incomplete URL substring sanitization","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/46"
"src/electron/agent/tools/canvas-tools.ts",316,"Incomplete URL scheme check","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/45"
"src/renderer/components/BrowserWorkbenchView.tsx",1523,"DOM text reinterpreted as HTML","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/44"
"src/renderer/components/BrowserView.tsx",156,"DOM text reinterpreted as HTML","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/43"
"src/renderer/utils/email-html-sanitize.ts",27,"Bad HTML filtering regexp","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/42"
"src/renderer/components/WebArtifactViewer.tsx",97,"Bad HTML filtering regexp","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/41"
"src/electron/mailbox/MailboxService.ts",981,"Bad HTML filtering regexp","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/40"
"src/electron/gateway/channels/email-client.ts",187,"Bad HTML filtering regexp","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/39"
"src/electron/agent/tools/web-fetch-tools.ts",513,"Bad HTML filtering regexp","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/38"
"src/electron/agent/tools/gmail-tools.ts",123,"Bad HTML filtering regexp","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/37"
"resources/skills/llm-wiki/scripts/wiki-workbench-lib.mjs",157,"Bad HTML filtering regexp","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/36"
"src/renderer/components/MainContent/markdown-normalization.ts",269,"Incomplete string escaping or encoding","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/35"
"src/electron/utils/pptx-extractor.ts",502,"Incomplete string escaping or encoding","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/34"
"src/electron/utils/json-utils.ts",175,"Incomplete string escaping or encoding","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/33"
"src/electron/memory/DurableContextService.ts",73,"Incomplete string escaping or encoding","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/32"
"src/electron/mailbox/MailboxService.ts",3521,"Incomplete string escaping or encoding","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/31"
"src/electron/computer-use/window-isolation.ts",99,"Incomplete string escaping or encoding","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/30"
"src/electron/computer-use/window-isolation.ts",74,"Incomplete string escaping or encoding","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/29"
"src/electron/browser/browser-workbench-service.ts",106,"Incomplete string escaping or encoding","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/28"
"src/electron/agent/executor-completion-utils.ts",42,"Incomplete string escaping or encoding","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/27"
"src/renderer/components/InboxAgentPanel.tsx",261,"Double escaping or unescaping","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/26"
"src/renderer/components/AssistantMessageContent.tsx",172,"Double escaping or unescaping","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/25"
"src/electron/utils/pptx-extractor.ts",338,"Double escaping or unescaping","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/24"
"src/electron/utils/pptx-extractor.ts",168,"Double escaping or unescaping","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/23"
"src/electron/mailbox/MailboxService.ts",979,"Double escaping or unescaping","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/22"
"src/electron/gateway/channels/email-client.ts",185,"Double escaping or unescaping","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/21"
"src/electron/gateway/channels/email.ts",528,"Double escaping or unescaping","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/20"
"src/electron/agent/tools/gmail-tools.ts",121,"Double escaping or unescaping","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/19"
"src/electron/agent/search/duckduckgo-provider.ts",158,"Double escaping or unescaping","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/18"
"resources/skills/llm-wiki/scripts/wiki-workbench-lib.mjs",156,"Double escaping or unescaping","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/17"
"src/renderer/utils/email-html-sanitize.ts",25,"Incomplete multi-character sanitization","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/16"
"src/renderer/utils/email-html-sanitize.ts",25,"Incomplete multi-character sanitization","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/15"
"src/renderer/utils/email-html-sanitize.ts",25,"Incomplete multi-character sanitization","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/14"
"src/renderer/components/utils/attachment-content.ts",30,"Incomplete multi-character sanitization","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/13"
"src/electron/utils/pptx-extractor.ts",338,"Incomplete multi-character sanitization","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/12"
"src/electron/gateway/channels/email.ts",528,"Incomplete multi-character sanitization","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/11"
"src/electron/agent/tools/web-fetch-tools.ts",582,"Incomplete multi-character sanitization","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/10"
"src/electron/agent/tools/web-fetch-tools.ts",511,"Incomplete multi-character sanitization","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/9"
"src/electron/agent/tools/web-fetch-tools.ts",511,"Incomplete multi-character sanitization","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/8"
"src/electron/agent/tools/web-fetch-tools.ts",511,"Incomplete multi-character sanitization","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/7"
"src/electron/agent/skills/document.ts",1070,"Incomplete multi-character sanitization","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/6"
"src/electron/agent/search/duckduckgo-provider.ts",158,"Incomplete multi-character sanitization","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/5"
"src/electron/utils/webhook-auth.ts",29,"Polynomial regular expression used on uncontrolled data","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/4"
"src/electron/tunnels/relay.ts",324,"Polynomial regular expression used on uncontrolled data","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/3"
"src/shared/tool-call-text-sanitizer.ts",64,"Inefficient regular expression","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/2"
"src/renderer/utils/markdown-autolink.ts",11,"Inefficient regular expression","https://github.com/raid-ppcoe/CoWork-OS/security/code-scanning/1"
17 changes: 12 additions & 5 deletions resources/skills/llm-wiki/scripts/wiki-workbench-lib.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -153,15 +153,22 @@ export function normalizeRelativePath(filePath) {
}

export function stripHtml(html) {
return String(html || "")
.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, " ")
.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, " ")
.replace(/<svg\b[^<]*(?:(?!<\/svg>)<[^<]*)*<\/svg>/gi, " ")
// Remove script/style/svg blocks with their content. Loop until stable +
// allow trailing whitespace in the closing tag so split tags can't survive
// and `</script >` can't bypass the filter.
let text = String(html || "");
let prev;
do {
prev = text;
text = text.replace(/<(script|style|svg)\b[^>]*>[\s\S]*?<\/\1\s*>/gi, " ");
} while (text !== prev);
return text
.replace(/<[^>]+>/g, " ")
.replace(/&nbsp;/gi, " ")
.replace(/&amp;/gi, "&")
.replace(/&lt;/gi, "<")
.replace(/&gt;/gi, ">")
// Unescape ampersands last so a decoded `&` can't form another entity.
.replace(/&amp;/gi, "&")
.replace(/\s+/g, " ")
.trim();
}
Expand Down
8 changes: 7 additions & 1 deletion scripts/collect-public-adoption-stats.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,13 @@ async function fetchJson(url, options = {}) {
Accept: "application/vnd.github+json",
...options.headers,
};
if (token && url.includes("api.github.com")) {
let host = "";
try {
host = new URL(url).hostname.toLowerCase();
} catch {
// non-absolute URL: never attach the token
}
if (token && host === "api.github.com") {
headers.Authorization = `Bearer ${token}`;
headers["X-GitHub-Api-Version"] = "2022-11-28";
}
Expand Down
2 changes: 1 addition & 1 deletion src/electron/agent/executor-completion-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function normalizePromptForContracts(taskPrompt: string): string {
);
const withoutWorkflow = withoutAdditionalContext.replace(
new RegExp(
`\\n{2}${WORKFLOW_DECOMPOSITION_HEADER.replace(/[()]/g, "\\$&")}\\n[\\s\\S]*?(?=\\n{2}${USER_UPDATE_HEADER}|$)`,
`\\n{2}${WORKFLOW_DECOMPOSITION_HEADER.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\n[\\s\\S]*?(?=\\n{2}${USER_UPDATE_HEADER}|$)`,
"g",
),
"",
Expand Down
3 changes: 2 additions & 1 deletion src/electron/agent/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12177,7 +12177,8 @@
artifactKind: contract.artifactKind,
},
bestCandidateLength: bestCandidate.length,
bestCandidateHash: createHash("sha1").update(bestCandidate).digest("hex").slice(0, 12),
// ponytail: non-security fingerprint for diagnostics, not a password; sha256 to silence weak-algo scan
bestCandidateHash: createHash("sha256").update(bestCandidate).digest("hex").slice(0, 12),

Check failure

Code scanning / CodeQL

Use of password hash with insufficient computational effort High

Password from
a call to toStructuredProviderError
is hashed insecurely.
Password from
a call to toStructuredProviderError
is hashed insecurely.
Password from
a call to toStructuredProviderError
is hashed insecurely.
Password from
an access to OPENAI_OAUTH_DEFAULT_MODEL
is hashed insecurely.
Password from
an access to OPENAI_OAUTH_DEFAULT_MODEL
is hashed insecurely.
Password from
a call to applyConnectorOAuth
is hashed insecurely.
Password from
an access to oauthOutcome
is hashed insecurely.
Password from
an access to oauthError
is hashed insecurely.
directAnswer: {
bestCandidatePasses: this.responseDirectlyAddressesPrompt(bestCandidate, contract),
fallbackPasses: fallbackHasDirectAnswer,
Expand Down
16 changes: 11 additions & 5 deletions src/electron/agent/search/duckduckgo-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,17 +155,23 @@ export class DuckDuckGoProvider implements SearchProvider {
}

private stripHtml(html: string): string {
return html
.replace(/<b>/g, "")
.replace(/<\/b>/g, "")
.replace(/<[^>]+>/g, "")
.replace(/&amp;/g, "&")
// Strip tags; loop until stable so a partial tag can't leave a working tag
// behind after a single pass.
let text = html.replace(/<b>/g, "").replace(/<\/b>/g, "");
let prev: string;
do {
prev = text;
text = text.replace(/<[^>]+>/g, "");
} while (text !== prev);
return text
.replace(/&lt;/g, "<")
.replace(/&gt;/g, ">")
.replace(/&quot;/g, '"')
.replace(/&#x27;/g, "'")
.replace(/&#39;/g, "'")
.replace(/&nbsp;/g, " ")
// Unescape ampersands last so a decoded `&` can't form another entity.
.replace(/&amp;/g, "&")
.replace(/\s+/g, " ");
}

Expand Down
11 changes: 9 additions & 2 deletions src/electron/agent/skill-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -323,9 +323,16 @@ export class SkillRegistry {
*/
private isStaticCatalog(): boolean {
const url = this.registryUrl.toLowerCase();
let hostname = "";
try {
hostname = new URL(this.registryUrl).hostname.toLowerCase();
} catch {
// not an absolute URL; fall back to path-suffix checks below
}
return (
url.includes("raw.githubusercontent.com") ||
url.includes("github.io") ||
hostname === "raw.githubusercontent.com" ||
hostname === "github.io" ||
hostname.endsWith(".github.io") ||
url.endsWith("/registry") ||
url.endsWith("/registry/")
);
Expand Down
12 changes: 10 additions & 2 deletions src/electron/agent/skills/document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1066,8 +1066,16 @@ export class DocumentBuilder {
const _trRegex = /<tr[^>]*>([\s\S]*?)<\/tr>/gi;
const _tdThRegex = /<t[dh][^>]*>([\s\S]*?)<\/t[dh]>/gi;

// Helper to strip HTML tags
const stripTags = (str: string): string => str.replace(/<[^>]*>/g, "").trim();
// Helper to strip HTML tags. Loop until stable so a partial tag can't leave
// a working tag behind after a single pass.
const stripTags = (str: string): string => {
let prev: string;
do {
prev = str;
str = str.replace(/<[^>]*>/g, "");
} while (str !== prev);
return str.trim();
};

// Process in order of appearance
let _lastIndex = 0;
Expand Down
15 changes: 9 additions & 6 deletions src/electron/agent/tools/batch-image-tools.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { exec, execFile } from "child_process";
import { execFile } from "child_process";
import { promisify } from "util";
import * as os from "os";
import * as path from "path";
Expand All @@ -10,7 +10,6 @@ import { LLMTool } from "../llm/types";

type Any = any; // oxlint-disable-line typescript-eslint(no-explicit-any)

const execAsync = promisify(exec);
const execFileAsync = promisify(execFile);
const PROCESS_TIMEOUT_MS = 60_000;
const PROTECTED_WRITE_PATHS = [
Expand Down Expand Up @@ -349,10 +348,14 @@ export class BatchImageTools {
], { timeout: PROCESS_TIMEOUT_MS });
} catch {
// Fallback: try with `magick composite` (ImageMagick 7)
await execAsync(
`magick composite -dissolve ${opacity} -gravity ${gravity} ${JSON.stringify(wmPath)} ${JSON.stringify(inputPath)} ${JSON.stringify(outputPath)}`,
{ timeout: PROCESS_TIMEOUT_MS },
);
await execFileAsync("magick", [
"composite",
"-dissolve", String(opacity),
"-gravity", gravity,
wmPath,
inputPath,
outputPath,
], { timeout: PROCESS_TIMEOUT_MS });
}
}

Expand Down
13 changes: 11 additions & 2 deletions src/electron/agent/tools/browser-tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ import { normalizeBrowserUrl } from "../../browser/browser-session-manager";
import { evaluateNetworkPolicy } from "../../security/network-policy";
import { BuiltinToolsSettingsManager } from "./builtin-settings";

/** True if the URL's host is exactly the Google consent page (parsed, not substring-matched). */
function isGoogleConsentUrl(url: string): boolean {
try {
return new URL(url).hostname.toLowerCase() === "consent.google.com";
} catch {
return false;
}
}

// oxlint-disable-next-line typescript-eslint/no-explicit-any
type Any = any;
type BrowserProvider = "local" | "browser-use-cloud";
Expand Down Expand Up @@ -1532,7 +1541,7 @@ export class BrowserTools {
this.getSessionId(input),
);
const currentUrl = typeof current?.url === "string" ? current.url : "";
if (!allow_consent && currentUrl.includes("consent.google.com")) {
if (!allow_consent && isGoogleConsentUrl(currentUrl)) {
throw new Error("Consent page detected; dismiss consent before taking screenshot.");
}
if (Array.isArray(disallow_url_contains) && disallow_url_contains.length > 0) {
Expand Down Expand Up @@ -1572,7 +1581,7 @@ export class BrowserTools {

if (!allow_consent) {
const currentUrl = await this.browserService.getCurrentUrl();
if (currentUrl.includes("consent.google.com")) {
if (isGoogleConsentUrl(currentUrl)) {
throw new Error("Consent page detected; dismiss consent before taking screenshot.");
}
}
Expand Down
16 changes: 5 additions & 11 deletions src/electron/agent/tools/canvas-tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,17 +306,11 @@ export class CanvasTools {
const value = String(ref || "").trim().toLowerCase();
if (!value) return true;
if (value.startsWith("#")) return true;
if (value.startsWith("//")) return true;
if (
value.startsWith("http://") ||
value.startsWith("https://") ||
value.startsWith("data:") ||
value.startsWith("blob:") ||
value.startsWith("about:") ||
value.startsWith("javascript:")
) {
return true;
}
if (value.startsWith("//")) return true; // protocol-relative URL
// Any explicit URI scheme (http:, https:, data:, blob:, about:, javascript:,
// vbscript:, filesystem:, etc.) means this is not a workspace-relative path we
// should resolve/inline. Detect the scheme robustly instead of enumerating prefixes.
if (/^[a-z][a-z0-9+.-]*:/.test(value)) return true;
return false;
}

Expand Down
16 changes: 12 additions & 4 deletions src/electron/agent/tools/gmail-tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,16 +118,24 @@ function decodeBody(data?: string): string {
}

function stripHtml(html: string): string {
return html
.replace(/<style[\s\S]*?<\/style>/gi, " ")
.replace(/<script[\s\S]*?<\/script>/gi, " ")
// Remove style/script blocks with their content. Loop until stable + allow
// trailing whitespace in the closing tag so split tags can't survive and
// `</script >` can't bypass the filter.
let text = html;
let prev: string;
do {
prev = text;
text = text.replace(/<(style|script)\b[^>]*>[\s\S]*?<\/\1\s*>/gi, " ");
} while (text !== prev);
return text
.replace(/<br\s*\/?>/gi, "\n")
.replace(/<\/p>/gi, "\n")
.replace(/<[^>]+>/g, " ")
.replace(/&nbsp;/g, " ")
.replace(/&amp;/g, "&")
.replace(/&lt;/g, "<")
.replace(/&gt;/g, ">")
// Unescape ampersands last so a decoded `&` can't form another entity.
.replace(/&amp;/g, "&")
.replace(/[ \t]+/g, " ")
.replace(/\n\s+/g, "\n")
.trim();
Expand Down
Loading