惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
Visual Studio Blog
小众软件
小众软件
博客园 - 【当耐特】
Last Week in AI
Last Week in AI
Jina AI
Jina AI
云风的 BLOG
云风的 BLOG
腾讯CDC
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Y
Y Combinator Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Engineering at Meta
Engineering at Meta
量子位
美团技术团队
I
InfoQ
Martin Fowler
Martin Fowler
MyScale Blog
MyScale Blog
博客园 - 聂微东
阮一峰的网络日志
阮一峰的网络日志
Blog — PlanetScale
Blog — PlanetScale

Recent Commits to openclaw:main

fix: guard openai-completions tool payload with supportsTools compat … · openclaw/openclaw@76a025c fix(slack): surface auth.test failure + normalize explicit-bot mentio… · openclaw/openclaw@995a020 chore(release): bump version to 2026.5.22 fix(ui): keep chat session search inline (#85490) · openclaw/openclaw@2601453 Policy: add secret and auth conformance checks (#81974) · openclaw/openclaw@c85feac fix(delivery): log failDelivery errors instead of silently swallowing… · openclaw/openclaw@f75789f fix(cli): validate debug proxy numeric options (#84260) · openclaw/openclaw@5c866a1 fix(daemon): use exit code instead of localized text for schtasks fal… · openclaw/openclaw@501e74d fix(auto-reply): enforce word boundary in slash command prefix match … · openclaw/openclaw@5c614de fix(message-tool): normalize send body aliases (#84102) docs: absorb maintainer docs sweep · openclaw/openclaw@e0fda55 fix(gateway): coalesce provider auth rewarms docs(voyage): clarify API key setup (#81803) · openclaw/openclaw@57178b1 docs(config): quote bracket config paths (#83058) · openclaw/openclaw@88f50e8 docs: link Copilot model availability (#76252) · openclaw/openclaw@14b2b8a test(telegram): await watchdog registration event · openclaw/openclaw@9fae5f7 ci: run binding command escape in release checks · openclaw/openclaw@4b63502 fix(tui): dismiss watchdog notice when response actually arrives (#77… · openclaw/openclaw@b741ddb test: add docker proof for plugin binding command escape · openclaw/openclaw@d756e1c test(telegram): wait for polling watchdog deterministically · openclaw/openclaw@7c9127c ci: skip pnpm auto repair in Crabbox shell · openclaw/openclaw@0241a6e fix(gateway): add .catch() to SIGTERM/SIGUSR1 signal handlers (#83131) fix: release cron runtime state after isolated runs (#85053) · openclaw/openclaw@247e536 fix(cron): suppress fatal error completion announce (#83724) · openclaw/openclaw@0c7220f fix(exec): parse nested approval metadata in async followups (#72268) · openclaw/openclaw@34c441c ci: share Crabbox hydrate pnpm store · openclaw/openclaw@7552634 chore(release): refresh plugin SDK baseline · openclaw/openclaw@736e7de ci(release): harden node setup before pnpm cache · openclaw/openclaw@a26aba6 ci(release): pass node pin to pnpm setup ci: use stable pnpm wrapper for Crabbox hydrate · openclaw/openclaw@b00d306 docs: refine maintainer docs sweep docs(memory): add guidance for action-sensitive memories (#82788) · openclaw/openclaw@bd04b1e docs(feishu): add dynamicAgentCreation and per-user isolation docs (#… docs(secrets): clarify agent-readable plaintext boundary (#84574) · openclaw/openclaw@ce5dcb0 docs(channels): document ackReactionScope for Slack & Telegram (DM go… · openclaw/openclaw@bbbed26 build(pnpm): use packageManager as pnpm source · openclaw/openclaw@a0702e1 ci: export Crabbox hydrate pnpm layout · openclaw/openclaw@f6840ac fix(gateway): preserve fresh agent session state · openclaw/openclaw@6f41653 fix(gateway): attribute agent wait timeouts ci: keep Crabbox hydrate runs reusable · openclaw/openclaw@489ea84 Speed up /models browse replies (#84735) · openclaw/openclaw@936dfaa docs: update changelog for plugin binding command escape (#85188) · openclaw/openclaw@9fc5346 Let binding commands escape plugin routes · openclaw/openclaw@af12082 ci: fix Crabbox hydrate pnpm modules dir · openclaw/openclaw@c9b17c5 Restore Control UI gateway token pairing [AI] (#85459) · openclaw/openclaw@10cb0a5 fix(docker): accept single-object pnpm list output · openclaw/openclaw@5e97045 fix: apply docs sweep updates · openclaw/openclaw@59aef2f fix(update): roll back failed git updates · openclaw/openclaw@769fd0b test(docker): expect prod store seed command fix(agents): bound embedded compaction write locks · openclaw/openclaw@46de078 fix(update): repair managed npm plugin peers · openclaw/openclaw@571f364 fix(update): repair managed npm plugin peers (#83794) (thanks @fuller… · openclaw/openclaw@de8a82a fix(telegram): honor table mode in outbound chunks (#85455) · openclaw/openclaw@7fc691a fix(docker): precreate owned named volume targets (#85454) · openclaw/openclaw@d8b9736 fix(ui): strip ANSI from displayed gateway logs (#85453) · openclaw/openclaw@664611c fix(skills): accept macos os requirement on darwin (#85451) fix(gateway): preserve message-tool replies in chat history test: track Docker prod store seed command · openclaw/openclaw@9a816f4 fix: satisfy prod store package list lint · openclaw/openclaw@d5247d0 test(plugins): clear lookup metadata memo fix(docker): seed prod store before offline prune · openclaw/openclaw@6788aa1 fix(memory): expand home paths in extra memory paths (#85449) · openclaw/openclaw@48bf037 docs: add security FAQ guidance chore(deps): refresh npm shrinkwraps docs: clarify OpenAI HTTP client guidance docs: remove stale showcase intro videos · openclaw/openclaw@00d3dca fix(gateway): point model override error to config docs docs: document secrets provider plan fields docs: clarify media directive formatting · openclaw/openclaw@c876fec docs: align memory search cache default refactor(ios): centralize setup auth parsing test(release): wait for config reload log proof refactor(ios): consolidate manual auth override inputs · openclaw/openclaw@d93c597 fix(ui): hide thinking options for non-reasoning models (#85406) · openclaw/openclaw@bb4d88e fix(ui): attach pasted data image text (#85392) · openclaw/openclaw@a03a8d9 fix(gateway): preserve OpenAI usage aliases in chat history (#85383) · openclaw/openclaw@d9c6c5f feat(ios): add realtime talk relay mode · openclaw/openclaw@e730e9b fix(browser): hint WSL portproxy CDP empty replies (#85379) · openclaw/openclaw@933f01c fix(installer): persist portable Git on Windows · openclaw/openclaw@5b90a48 fix(opencode-go): strip Kimi reasoning replay fields (#85377) · openclaw/openclaw@d22bcfc fix(build): normalize cache paths on Windows (#85437) · openclaw/openclaw@81d22c8 fix(update): detect nested macOS gateway ancestry (#85391) · openclaw/openclaw@adc6adc fix(docker): seed offline prune store in runtime stage · openclaw/openclaw@faf2a6c fix(ci): stabilize npm shrinkwrap metadata · openclaw/openclaw@21bedd3 fix(codex): route node exec through OpenClaw tools · openclaw/openclaw@5cc0dbc test(installer): track portable node root helper · openclaw/openclaw@9364b21 fix(ui): sync talk transcript translations fix(ui): localize talk transcript labels · openclaw/openclaw@8fc48af fix(release): stabilize config restart QA · openclaw/openclaw@cc91ff0 fix(installer): extract portable Node directly test(qa-lab): report scenario pack coverage · openclaw/openclaw@dcd98bf fix(plugins): drop stale tlon tool contract · openclaw/openclaw@d70dc4b fix(installer): prefer tar for portable Node extraction · openclaw/openclaw@a54a881 fix(codex): deliver native subagent completions feat: add context-engine host capability requirements (#84994) · openclaw/openclaw@cff5244 fix(release): keep shrinkwrap pinned to pnpm lock · openclaw/openclaw@9d24fde fix: surface plan updates as status notices · openclaw/openclaw@dc04503 test(google): narrow web search fake timers · openclaw/openclaw@fe7d13c fix(installer): extract portable Node with ZipFile · openclaw/openclaw@ffa6cd8 fix(gateway): defer provider auth prewarm after startup (#85369) · openclaw/openclaw@69255f8
fix(security): escape entry.id in HTML export to prevent attribute XS… · openclaw/openclaw@7bc4a33
SebTardif · 2026-05-23 · via Recent Commits to openclaw:main

@@ -494,6 +494,104 @@ describe("export html security hardening", () => {

494494

);

495495

});

496496497+

it("escapes entry.id in element id and data-entry-id attributes", async () => {

498+

const xssId = `"><script>alert(1)</script><div data-x="`;

499+

const session: SessionData = {

500+

header: { id: "session-xss-id", timestamp: now() },

501+

entries: [

502+

{

503+

id: xssId,

504+

parentId: null,

505+

timestamp: now(),

506+

type: "message",

507+

message: { role: "user", content: "hello" },

508+

},

509+

{

510+

id: "safe-child",

511+

parentId: xssId,

512+

timestamp: now(),

513+

type: "message",

514+

message: {

515+

role: "assistant",

516+

content: [{ type: "text", text: "world" }],

517+

},

518+

},

519+

],

520+

leafId: "safe-child",

521+

systemPrompt: "",

522+

tools: [],

523+

};

524+525+

const { document } = await renderTemplate(session);

526+

const messages = requireElement(document.getElementById("messages"), "messages root missing");

527+528+

// Core XSS prevention: no <script> tags should be injected into the DOM

529+

expect(messages.querySelectorAll("script").length).toBe(0);

530+531+

// No attribute breakout: onmouseover, data-x must not appear as real attributes

532+

expect(messages.querySelector("[onmouseover]")).toBeNull();

533+534+

// The copy-link button must exist with the payload safely contained

535+

const copyBtn = requireElement(

536+

messages.querySelector(".copy-link-btn"),

537+

"copy-link button missing",

538+

);

539+

// data-entry-id must be present as a proper attribute (not broken out)

540+

expect(copyBtn.hasAttribute("data-entry-id")).toBe(true);

541+

// No stray attributes from the payload

542+

expect(copyBtn.hasAttribute("data-x")).toBe(false);

543+544+

// The user message element must not have attribute breakout either

545+

const userMsg = requireElement(

546+

messages.querySelector(".user-message"),

547+

"user message element missing",

548+

);

549+

expect(userMsg.getAttribute("data-x")).toBeNull();

550+

// The element id must start with entry- (the payload is contained within)

551+

const elementId = userMsg.getAttribute("id") ?? "";

552+

expect(elementId.startsWith("entry-")).toBe(true);

553+

});

554+555+

it("copy-link round-trip: dataset.entryId matches raw entry.id after browser decoding", async () => {

556+

// IDs with characters that need HTML escaping but should round-trip correctly

557+

const specialId = `msg-with"quotes&amp's`;

558+

const session: SessionData = {

559+

header: { id: "session-roundtrip", timestamp: now() },

560+

entries: [

561+

{

562+

id: specialId,

563+

parentId: null,

564+

timestamp: now(),

565+

type: "message",

566+

message: { role: "user", content: "test" },

567+

},

568+

],

569+

leafId: specialId,

570+

systemPrompt: "",

571+

tools: [],

572+

};

573+574+

const { document } = await renderTemplate(session);

575+

const messages = requireElement(document.getElementById("messages"), "messages root missing");

576+577+

// The copy-link button should exist

578+

const copyBtn = requireElement(

579+

messages.querySelector(".copy-link-btn"),

580+

"copy-link button missing",

581+

);

582+583+

// Browser decodes HTML entities in dataset reads, so dataset.entryId

584+

// must return the RAW entry.id (not the HTML-escaped version).

585+

// This is essential for buildShareUrl() to produce the correct URL.

586+

const datasetValue = (copyBtn as HTMLElement).dataset.entryId;

587+

expect(datasetValue).toBe(specialId);

588+589+

// The DOM element id must also round-trip: getElementById should find it

590+

const userMsg = document.getElementById(`entry-${specialId}`);

591+

expect(userMsg).not.toBeNull();

592+

expect(userMsg?.classList.contains("user-message")).toBe(true);

593+

});

594+497595

it("escapes markdown data-image attributes", async () => {

498596

const dataImage = "data:image/png;base64,AAAA";

499597

const session: SessionData = {