Skill flagged — suspicious patterns detected

ClawHub Security flagged this skill as suspicious. Review the scan results before using.

crawl requirement from confluence

读取Confluence需求文档并整理成指定格式。采集原则是"忠实记录",而非"需求分析"。输出包括:{序号}_{标题}.md(每个页面一个Markdown文件)、requirement-meta.md(元信息)、images/(所有图片,文件中包含图片引用)。

MIT-0 · Free to use, modify, and redistribute. No attribution required.
0 · 19 · 0 current installs · 0 all-time installs
MIT-0
Security Scan
VirusTotalVirusTotal
Suspicious
View report →
OpenClawOpenClaw
Suspicious
medium confidence
Purpose & Capability
The skill's name/description (Confluence reader that converts pages to Markdown and saves images) matches the SKILL.md instructions: enumerating page trees, converting HTML→MD, and saving images. There are no unrelated binaries or external services requested. However, the requirement to always fetch every child page (no partial fetch) is strict and may be disproportionate for many legitimate uses.
!
Instruction Scope
Runtime instructions tell the agent/user to (a) open a browser and stay logged in (relying on a session), (b) execute JavaScript in the browser console to scrape page links, (c) optionally use a cookie with the Confluence REST API, (d) recursively fetch all child pages and images without skipping, and (e) run PowerShell that deletes zip files and output subdirectories when storage thresholds are exceeded. These behaviors broaden the scope beyond simple conversion: they depend on user session cookies, require executing browser console JS and local PowerShell, and include destructive file operations that may affect other data.
Install Mechanism
No install spec or code is included (instruction-only), so nothing is downloaded or installed by the skill itself. That reduces supply-chain risk. Note: the agent's runtime instructions still call for executing local PowerShell and browser JS, which is operational risk but not an installation risk.
!
Credentials
The skill declares no env vars/credentials, but the instructions require a logged-in browser session and include functions that accept a cookie string for REST API calls — effectively requiring session credentials that are not declared. The cleanup script targets workspaceDir and *.zip files in the workspace root, which may contain unrelated user data; that access is broader than just writing the skill's own outputs.
Persistence & Privilege
The skill does not request always:true or otherwise demand permanent inclusion. It does instruct creating timestamped output directories and removing old directories/zip files within configured paths, which is normal for a scraper but carries the deletion risk noted above.
What to consider before installing
This skill appears to do what it says (crawl Confluence and save Markdown/images) but has two practical risks you should consider before installing: (1) it insists on crawling every child page and will not stop mid-run, which can download large amounts of potentially sensitive data; (2) its cleanup script will delete the oldest zip files and output subdirectories under the configured workspace path — that could remove unrelated files. Also, the tool relies on a logged-in browser session or cookies (session credentials) that are not declared as required environment variables; avoid pasting cookies into untrusted tools. Recommendations: set outputDir and workspaceDir to an isolated test folder, review/modify the cleanup script (or disable automatic deletion), test on a small subtree first, and prefer using a dedicated Confluence API token (scoped to read-only) instead of browser cookies. If you can provide the skill's source code or clarify how cookies/session data are handled, I can reassess with higher confidence.

Like a lobster shell, security has layers — review code before you run it.

Current versionv1.0.1
Download zip
latestvk973eaxd5t4yv509wva6cj51rs8311z5

License

MIT-0
Free to use, modify, and redistribute. No attribution required.

SKILL.md

Theo Confluence Reader

全局配置

# Confluence 配置(根据实际环境修改)
$confluenceBaseUrl = "https://confluence.xxx.com"
$outputDir = "C:\Users\xxx\.openclaw\workspace\output"
$workspaceDir = "C:\Users\xxx\.openclaw\workspace"
$maxSize = 1GB
$warnThreshold = 0.8

核心原则

这个skill的职责是"忠实采集",不是"需求分析"

  • 只做格式转换(HTML → MD),不做内容删减、概括或精简
  • 保留原文的所有细节,包括表格、列表、备注、批注等
  • 不要对原文做任何主观判断、删除或重组

执行规则(强制)

⚠️ 必须抓取所有页面,不允许部分抓取或偷懒

默认行为

  1. 自动抓取全部:给定一个Confluence页面链接后,必须抓取该页面及其所有子页面的全部内容
  2. 不允许只抓索引:不能只抓父页面或索引页就停下来,必须深入到每个叶子节点
  3. 不允许跳过:不能因为"内容太多"或"时间太长"而跳过某些页面

唯一例外:确认模式(仅允许询问一次)

如果预估采集时间超过5分钟或页面数量超过10个,可以先整理大纲并预估资源,返回给用户确认。

但必须遵守以下规则

  • 只能询问一次:确认后必须执行完整,不能再次询问
  • 大纲必须包含
    • 所有待抓取页面的完整列表
    • 预估页面数量
    • 预估时间和资源消耗
  • 确认后必须执行:用户确认后,立即开始抓取所有页面,中途不能停止或询问
  • 禁止多次询问:一旦用户确认后,不能以任何理由再次询问是否继续

示例

错误做法(禁止)

  • 只抓父页面索引,给用户后说"详细内容需要再抓"
  • 抓了一部分后说"太多了要不要继续"
  • 用户确认后 又问"这个子页面要不要抓"

正确做法

  • 要么直接全部抓完
  • 要么先给大纲确认,确认后全部抓完

存储上限

output/ 目录总大小上限:1GB

  • 每次创建新目录前检查总大小
  • 超过 80%(800MB)时:自动删除最早的目录
  • 超过 100%(1GB)时:强制删除最早的目录直到低于 80%

检查并清理脚本

$outputDir = "C:\Users\xxx\.openclaw\workspace\output"
$workspaceDir = "C:\Users\xxx\.openclaw\workspace"
$maxSize = 1GB
$warnThreshold = 0.8

if (!(Test-Path $outputDir)) { 
    New-Item -ItemType Directory -Path $outputDir -Force
}

# 计算 output 目录大小 + workspace 根目录下的 zip 文件大小
$outputSize = 0
$zipSize = 0

$outputItems = Get-ChildItem $outputDir -Recurse -ErrorAction SilentlyContinue
if ($outputItems) {
    $outputSize = ($outputItems | Measure-Object -Property Length -Sum).Sum
}

$zipFiles = Get-ChildItem $workspaceDir -Filter "*.zip" -ErrorAction SilentlyContinue
if ($zipFiles) {
    $zipSize = ($zipFiles | Measure-Object -Property Length -Sum).Sum
}

$totalSize = $outputSize + $zipSize

if ($totalSize -gt ($maxSize * $warnThreshold)) {
    Write-Host "存储超过 80%,开始清理..."
    
    # 1. 删除最早的 zip 文件
    if ($zipSize -gt 0) {
        $zipFilesSorted = $zipFiles | Sort-Object LastWriteTime
        foreach ($zip in $zipFilesSorted) {
            if ($totalSize -lt ($maxSize * $warnThreshold)) { break }
            $z = $zip.Length
            Remove-Item $zip.FullName -Force
            $totalSize -= $z
            Write-Host "已删除压缩包: $($zip.Name)"
        }
    }
    
    # 2. 删除最早的 output 子目录
    $dirs = Get-ChildItem $outputDir -Directory -ErrorAction SilentlyContinue | Sort-Object LastWriteTime
    foreach ($dir in $dirs) {
        if ($totalSize -lt ($maxSize * $warnThreshold)) { break }
        $dirSize = (Get-ChildItem $dir.FullName -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum
        if ($dirSize -gt 0) {
            Remove-Item $dir.FullName -Recurse -Force
            $totalSize -= $dirSize
            Write-Host "已删除: $($dir.Name)"
        }
    }
}

输出目录结构

重要:每次运行都会在 output/ 下创建一个以"页面标题_时间戳"命名的独立目录,避免文件混淆。

pageId获取方式

  • 从Confluence URL中提取:/pages/viewpage.action?pageId=272188760pageId=272188760
  • 或从页面源码中获取
output/
├── 页面标题_2026-03-13_2030/
│   ├── 01_需求概述.md          # 页面1的MD转换版
│   ├── 02_登录注册.md          # 页面2的MD转换版
│   ├── 03_系统首页.md          # 页面3的MD转换版
│   ├── ...                     # 其他页面
│   ├── requirement-meta.md    # 元信息(整个采集任务的元信息)
│   └── images/                 # 关联图片
│       ├── 01_需求概述_功能架构图.png
│       ├── 02_登录注册.png
│       └── ...

时间戳格式YYYY-MM-DD_HHmm(年月日_时分)

前置要求

必须先登录 Confluence

  1. 在运行 OpenClaw 的机器上打开浏览器
  2. 访问 Confluence 页面并完成登录
  3. 保持登录状态,后续的图片下载和内容获取都依赖这个已登录的 session

操作流程

Step 1: 分析页面结构 + 创建输出目录 + 检查存储上限

⚠️ 重要:必须抓取所有子页面

  • 这一步必须展开页面树,列出所有子页面(包括二级、三级、四级等全部层级)
  • 不能只抓父页面就停止
  • 记录每个子页面的:pageId、标题、层级

输入验证

param(
    [Parameter(Mandatory=$true)]
    [string]$confluenceUrl
)

# 验证URL格式
if ($confluenceUrl -notmatch 'https?://[^/]+/pages/(viewpage\.action\?pageId=|viewpage\.action\?title=)') {
    throw "无效的Confluence URL,请提供形如 https://confluence.xxx.com/pages/viewpage.action?pageId=123456 的URL"
}

# 提取pageId(如果URL中包含)
if ($confluenceUrl -match 'pageId=(\d+)') {
    $rootPageId = $matches[1]
    Write-Host "根页面ID: $rootPageId"
}

获取完整页面树的两种方法:

方法1:通过浏览器页面树获取(默认推荐)

  1. 用浏览器打开用户提供的 Confluence URL
  2. 在页面左侧找到"页面树结构"
  3. 点击"展开全部"或手动展开所有层级(包括二级、三级、四级...直到叶子节点)
  4. 使用 browser evaluate 获取页面树的完整结构:
    // 在浏览器控制台执行,获取所有页面链接
    const links = Array.from(document.querySelectorAll('a[href*="pageId="]')).map(a => ({
        title: a.textContent.trim(),
        pageId: a.href.match(/pageId=(\d+)/)?.[1],
        href: a.href
    }));
    console.log(JSON.stringify(links, null, 2));
    
  5. 解析获取的数据,提取所有 pageId 和标题
  6. ⚠️ 关键:必须确保页面树完全展开,所有层级的子页面都被展开
  7. 确认总共有多少个页面需要获取

方法2:通过 Confluence REST API 获取(备选)

# 获取页面及其所有子页面
function Get-ConfluencePageTree {
    param(
        [string]$baseUrl = "https://confluence.xxx.com",
        [string]$rootPageId,
        [string]$cookie  # 登录 cookie
    )
    
    $pages = @()
    
    # 获取当前页面的直接子页面
    $apiUrl = "$baseUrl/rest/api/content/$rootPageId/child/page"
    $headers = @{
        "Cookie" = $cookie
        "Content-Type" = "application/json"
    }
    
    $response = Invoke-RestMethod -Uri $apiUrl -Headers $headers -Method Get
    foreach ($page in $response.results) {
        $pages += @{
            pageId = $page.id
            title = $page.title
            type = $page.type
        }
        
        # 递归获取子页面的子页面
        $childPages = Get-ConfluencePageTree -baseUrl $baseUrl -rootPageId $page.id -cookie $cookie
        $pages += $childPages
    }
    
    return $pages
}

# 调用
$allPages = Get-ConfluencePageTree -rootPageId $rootPageId -cookie $cookie
Write-Host "共获取 $($allPages.Count) 个页面"

检查并清理存储(如果超过80%上限)

# 复用全局配置的变量,或直接使用以下默认值
$outputDir = "C:\Users\xxx\.openclaw\workspace\output"
$workspaceDir = "C:\Users\xxx\.openclaw\workspace"
$maxSize = 1GB
$warnThreshold = 0.8

if (!(Test-Path $outputDir)) { 
    New-Item -ItemType Directory -Path $outputDir -Force
}

# 计算 output 目录大小 + workspace 根目录下的 zip 文件大小
$outputSize = 0
$zipSize = 0

$outputItems = Get-ChildItem $outputDir -Recurse -ErrorAction SilentlyContinue
if ($outputItems) {
    $outputSize = ($outputItems | Measure-Object -Property Length -Sum).Sum
}

$zipFiles = Get-ChildItem $workspaceDir -Filter "*.zip" -ErrorAction SilentlyContinue
if ($zipFiles) {
    $zipSize = ($zipFiles | Measure-Object -Property Length -Sum).Sum
}

$totalSize = $outputSize + $zipSize

if ($totalSize -gt ($maxSize * $warnThreshold)) {
    Write-Host "存储超过 80%,开始清理..."
    
    # 1. 删除最早的 zip 文件
    if ($zipSize -gt 0) {
        $zipFilesSorted = $zipFiles | Sort-Object LastWriteTime
        foreach ($zip in $zipFilesSorted) {
            if ($totalSize -lt ($maxSize * $warnThreshold)) { break }
            $z = $zip.Length
            Remove-Item $zip.FullName -Force
            $totalSize -= $z
            Write-Host "已删除压缩包: $($zip.Name)"
        }
    }
    
    # 2. 删除最早的 output 子目录
    $dirs = Get-ChildItem $outputDir -Directory -ErrorAction SilentlyContinue | Sort-Object LastWriteTime
    foreach ($dir in $dirs) {
        if ($totalSize -lt ($maxSize * $warnThreshold)) { break }
        $dirSize = (Get-ChildItem $dir.FullName -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum
        if ($dirSize -gt 0) {
            Remove-Item $dir.FullName -Recurse -Force
            $totalSize -= $dirSize
            Write-Host "已删除: $($dir.Name)"
        }
    }
}

创建带时间戳的输出目录

# 获取当前时间戳
$timestamp = Get-Date -Format "yyyy-MM-dd_HHmm"
# 页面标题(去除非法字符)
$safeTitle = "页面标题" -replace '[\\/:*?"<>|]', '_'
# 创建目录
$outputDir = "C:\Users\root\.openclaw\workspace\output\${safeTitle}_${timestamp}"
New-Item -ItemType Directory -Path "$outputDir\images" -Force

后续所有文件都写入这个新创建的目录,而不是直接写进 output/ 根目录。

Step 2: 获取每个页面的内容(使用 sessions_spawn)

⚠️ 必须抓取所有页面,不允许选择性抓取

重要:由于需要获取多个页面,必须使用 sessions_spawn 派发子任务并行处理。

步骤

  1. 分析所有pageId列表(从页面URL或页面树中提取)
  2. 派发子任务获取所有页面的文字内容
  3. 派发子任务下载所有页面的图片
  4. 监控子任务直到完成

获取页面内容的方法

  1. 使用 browser 访问 Confluence 页面
  2. 获取页面完整HTML内容(browser evaluate 或 snapshot)
  3. 将HTML转换为Markdown格式

HTML转Markdown推荐方法

  • 方法1:使用 Python markdownify
    python -m pip install markdownify
    python -c "from markdownify import markdownify; print(markdownify(html_content))"
    
  • 方法2:使用 Node.js turndown
    npm install -g turndown
    echo $htmlContent | turndown
    
  • 方法3:使用在线API(如 html2md.com 的API)

关键要求:转换过程中不得删除任何内容,包括:

  • 表格(保持表格结构)
  • 图片引用(转换为 ![](images/xxx.png) 格式)
  • 代码块(保持原始格式)
  • 特殊字符和格式

Step 3: 获取页面图片(使用 curl 直接下载)

重要:使用 curl 直接下载图片原始文件,不再使用 browser 截图方式。

⚠️ 必须为每个页面下载图片,不管页面层级

不管是一级页面、二级页面、三级页面还是更深层次的子页面,都必须下载该页面的所有图片附件!

关键原则:每个页面独立获取图片 — 页面层级不影响图片下载,父页面的图片 ≠ 子页面的图片,子页面需要单独获取自己的图片!

⚠️ 前置要求:必须先获取登录 Cookie

由于 Confluence 私有图片需要登录才能下载,需要用户手动提供 Cookie

  1. 用户在浏览器中登录 Confluence

  2. 按 F12 打开开发者工具 → Application/Storage → Cookies

  3. 复制以下 cookie 的值:

    • JSESSIONID
    • CONFLAuth
    • 其他可能需要的 cookie(如 _gatgw_l7_route 等)
  4. 将完整 cookie 字符串提供给模型,格式如:

    _ga=GA1.1.xxx; pt_66be4504=xxx; JSESSIONID=xxx; tgw_l7_route=xxx
    

获取认证Cookie

# 用户提供的 cookie(直接使用,无需额外处理)
$cookie = "用户提供的完整cookie字符串"

图片获取步骤

  1. 遍历所有页面:对 Step 1 中获取的每一个页面(包括所有层级的一级、二级、三级...子页面)
  2. 对每个pageId,访问附件页面:https://confluence.xxx.com/pages/viewpageattachments.action?pageId={pageId}
  3. 使用 curl 获取附件列表页面源码
  4. 解析 data-attachment-filename 属性,找到该页面所有图片附件
  5. 使用 curl 下载每个图片
  6. 重复步骤1-5直到所有页面的图片都下载完成

图片命名规则

  • 格式:{页面序号}_{页面名称}.{扩展名}
  • 例如:01_需求概述_功能架构图.png02_登录注册.png

curl 下载命令示例

$cookie = "用户提供的cookie"
$imageUrl = "https://confluence.xxx.com/download/attachments/272188760/image-2026-3-3_14-10-42.png?api=v2"
$outputFile = "C:\Users\root\.openclaw\workspace\output\images\01_需求概述_功能架构图.png"

curl.exe -L -o $outputFile $imageUrl -H "Cookie: $cookie"

注意事项

  • 使用 curl.exe 而非 PowerShell 内置 curl 别名
  • 添加 -L 参数跟随重定向
  • 必须携带完整登录 Cookie 才能下载私有图片
  • Cookie 可能有有效期限制,如失效需让用户重新提供

curl 下载脚本(含错误处理和重试)

# 配置
$cookie = "JSESSIONID=xxx; CONFLAuth=xxx"  # 替换为实际 cookie
$imagesDir = "$outputDir\images"
$maxRetries = 3

# 创建 images 目录
if (!(Test-Path $imagesDir)) {
    New-Item -ItemType Directory -Path $imagesDir -Force
}

# 图片列表(从附件页面解析得到)
$imageList = @(
    @{pageId="272191284"; filename="image.png"; ext="png"},
    @{pageId="272191284"; filename="photo.jpg"; ext="jpg"}
)

$index = 1
foreach ($img in $imageList) {
    $imageUrl = "https://confluence.xxx.com/download/attachments/$($img.pageId)/$($img.filename)"
    $outputFile = "$imagesDir\$($img.pageId)_$index.$($img.ext)"
    
    # 重试逻辑
    $success = $false
    for ($retry = 1; $retry -le $maxRetries; $retry++) {
        Write-Host "尝试下载 ($retry/$maxRetries): $imageUrl"
        
        $result = curl.exe -L -o $outputFile $imageUrl `
            -H "Cookie: $cookie" `
            -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" `
            --silent --show-error `
            2>&1
        
        # 检查文件是否成功下载
        if ((Test-Path $outputFile) -and (Get-Item $outputFile).Length -gt 0) {
            $success = $true
            Write-Host "已下载: $outputFile"
            break
        } else {
            Write-Host "下载失败,等待重试..."
            Start-Sleep -Seconds 2
        }
    }
    
    if (-not $success) {
        Write-Host "警告: 图片下载失败 - $imageUrl" -ForegroundColor Yellow
    }
    
    $index++
}

Write-Host "图片下载完成,共 $($imageList.Count) 张"

注意事项

  • 使用 curl.exe 而非 PowerShell 内置 curl 别名
  • 添加 -L 参数跟随重定向
  • 保留原始文件格式(png/jpg/svg等)
  • 必须携带登录 Cookie 才能下载私有图片
  • 添加重试逻辑应对网络不稳定
  • 下载后检查文件大小确保下载成功

Step 4: 生成输出文件

所有文件都写入 Step 1 创建的 $outputDir 目录

4.1 {序号}_{标题}.md(每个页面一个)

将Confluence页面的HTML内容忠实转换为Markdown格式。

关键:必须插入图片引用!

在生成 md 文件时,对于该页面关联的每张图片,必须在适当位置插入图片引用:

# 假设当前页面是 "02_登录注册",该页面有 2 张图片
# images/ 目录中的文件:
#   - 02_登录注册.png
#   - 02_登录注册_2.png

# 在 md 文件内容中插入图片引用(建议放在页面标题下方或相关章节后)

$markdownContent = @"
# 2.1 登录注册(一期交付)

![](images/02_登录注册.png)

## 1、功能设计

...

## 2、原型图

![](images/02_登录注册_2.png)

...
"@

# 写入文件
$mdFileName = "02_登录注册.md"
$mdFilePath = Join-Path $outputDir $mdFileName
Set-Content -Path $mdFilePath -Value $markdownContent -Encoding UTF8

图片引用规则

  • 格式:![](images/{图片文件名})
  • 位置:
    • 如果图片是功能架构图/流程图,放在页面标题下方或相应章节后
    • 如果是原型图,放在对应功能描述之后
    • 如果无法确定位置,放在页面末尾
  • 如果一个页面有多张图片,按文件名排序后依次插入

4.2 requirement-meta.md

# 采集元信息

- 来源页面: [Confluence 页面 URL]
- 采集根页面: [根页面标题和 URL]
- 采集时间: [ISO 8601 格式,如 2026-03-15T18:00:00+08:00]
- 采集环境: [Confluence URL 域名]
- 总页面数: [页面总数]
- 页面列表:
  - 01_需求概述 (pageId: 272188760)
  - 02_登录注册 (pageId: 272189290)
  - ...

写入 $outputDir\requirement-meta.md

4.3 images/ 目录

  • 保存所有下载的图片到 $outputDir\images\
  • 文件名格式:{序号}_{页面标题}_{图片描述}.{扩展名}
  • 例如:01_需求概述_功能架构图.png02_登录注册.png02_登录注册_2.png

Step 5: 打包输出

将整个output目录打包成zip文件,发送给用户。

打包命令

# 打包整个 output 目录
$timestamp = Get-Date -Format "yyyy-MM-dd_HHmm"
$zipName = "confluence_export_$timestamp.zip"
$zipPath = "C:\Users\root\.openclaw\workspace\$zipName"

# 使用 PowerShell Compress-Archive
Compress-Archive -Path "C:\Users\root\.openclaw\workspace\output\*" -DestinationPath $zipPath -Force

# 验证打包结果
if (Test-Path $zipPath) {
    $zipSize = (Get-Item $zipPath).Length
    Write-Host "打包完成: $zipName (大小: $([math]::Round($zipSize/1MB, 2)) MB)"
} else {
    Write-Host "打包失败!" -ForegroundColor Red
}

或者使用 7z(如果安装了中国)

7z a -r "$zipPath" "C:\Users\root\.openclaw\workspace\output\*"

输出文件后

  • 将 zip 文件路径返回给用户
  • 用户下载后可解压查看

注意事项

  1. 使用sessions_spawn:长时间任务必须使用sessions_spawn派发子任务并行处理

  2. 图片直接下载

    • 访问 viewpageattachments.action?pageId={pageId} 获取附件列表
    • 使用 curl 携带登录 Cookie 直接下载图片原始文件
    • 保留原始格式(png/jpg/svg等)
    • 添加重试逻辑(建议3次)确保稳定性
  3. 认证Cookie获取

    • 主session已登录,可以从browser获取Cookie
    • Cookie格式:JSESSIONID=xxx; CONFLAuth=xxx
    • 必须携带Cookie才能下载私有图片
  4. HTML转Markdown

    • 推荐使用 markdownify (Python) 或 turndown (Node.js)
    • 转换过程不得删除任何内容
    • 表格、代码块、图片引用需保持完整
  5. 存储管理

    • 每次创建新目录前检查存储上限
    • 超过80%自动清理最早的目录和zip文件
    • 注意处理空目录的边界情况
  6. 错误处理

    • 所有网络请求添加重试逻辑
    • 下载后验证文件大小
    • 记录错误日志以便排查
  7. 不删减内容:原文的每一个字都要保留

  8. 保留格式:表格、列表等都要完整保留

  9. 层级准确:严格按照Confluence的页面树层级整理

Files

1 total
Select a file
Select a file to preview.

Comments

Loading comments…