安全扫描
OpenClaw
安全
medium confidence该技能内部一致,通过 Maton 代理 LinkedIn API 调用,只请求单个 MATON_API_KEY 环境变量,符合文档行为。主要风险在于对 Maton 网关的信任,而非技能自身的不一致。
评估建议
该技能一致,通过 Maton 代理 LinkedIn 调用,只需 MATON_API_KEY。安装前,请验证对 Maton 的信任(gateway.maton.ai 等),因为 Maton 将处理 OAuth 流并操作您的 LinkedIn 账户。将 MATON_API_KEY 视为高权限密钥:如果可能,使用最小权限 Maton 密钥,阅读 Maton 的隐私/安全文档,考虑使用非关键 LinkedIn 账户进行测试,并准备在停止使用技能时旋转/吊销密钥。如果需要无第三方代理的直接控制,请选择仅要求您自己的 LinkedIn 凭据或直接使用官方 LinkedIn 端点的技能。...详细分析 ▾
✓ 用途与能力
名称和描述声称使用管理的 OAuth 进行 LinkedIn 集成;SKILL.md 文档记录了对 gateway.maton.ai 和 ctrl.maton.ai 的 API 和连接管理调用,仅要求 MATON_API_KEY。请求的工件(Maton API 密钥)与声明的目的一致。
✓ 指令范围
运行时指令明确,仅限于向 Maton 端点(gateway.maton.ai、ctrl.maton.ai、connect.maton.ai)发出 HTTP 请求,并指示用户在浏览器中完成 OAuth。指令不请求无关文件、系统路径或额外环境变量。
✓ 安装机制
无安装规范,仅有 SKILL.md 和许可证,无代码文件 — 这是指令式的,因此安装期间没有内容写入磁盘。这是最低风险的安装类别,且与技能内容匹配。
ℹ 凭证需求
仅要求 MATON_API_KEY,这与代理 OAuth 集成成比例。然而,该单个密钥很强大:Maton 将代表用户的 LinkedIn 连接/令牌看到和操作。技能不请求无关凭据,但用户应将 MATON_API_KEY 视为敏感。
✓ 持久化与权限
always 为 false,技能为用户可调用;不要求永久包含或系统范围的配置更改。允许自主调用(平台默认),但不与其他权限提升指标结合。
安全有层次,运行前请审查代码。
运行时依赖
无特殊依赖
版本
latestv1.0.62026/2/7
此版本无变化。版本号更新为 1.0.6。
● 无害
安装命令
点击复制官方npx clawhub@latest install linkedin-api
镜像加速npx clawhub@latest install linkedin-api --registry https://cn.longxiaskill.com
技能文档
通过托管 OAuth 认证访问 LinkedIn API。分享帖子、管理广告活动、检索个人资料和组织信息、上传媒体、访问广告库。
快速开始
# 获取当前用户个人资料
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/linkedin/rest/me')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('LinkedIn-Version', '202506')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
基础 URL
https://gateway.maton.ai/linkedin/rest/{resource}
网关将请求代理到 api.linkedin.com 并自动注入您的 OAuth token。
认证
所有请求都需要在 Authorization 头中包含 Maton API 密钥:
Authorization: Bearer $MATON_API_KEY
环境变量: 将您的 API 密钥设置为 MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
获取 API 密钥
- 在 maton.ai 登录或创建账户
- 访问 maton.ai/settings
- 复制您的 API 密钥
必需的请求头
LinkedIn REST API 需要版本头:
LinkedIn-Version: 202506
连接管理
在 https://ctrl.maton.ai 管理您的 LinkedIn OAuth 连接。
列出连接
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections?app=linkedin&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
创建连接
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'linkedin'}).encode()
req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
获取连接详情
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
响应:
{
"connection": {
"connection_id": "ba10eb9e-b590-4e95-8c2e-3901ff94642a",
"status": "ACTIVE",
"creation_time": "2026-02-07T08:00:24.372659Z",
"last_updated_time": "2026-02-07T08:05:16.609085Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "linkedin",
"metadata": {}
}
}
在浏览器中打开返回的 url 完成 OAuth 授权。
删除连接
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
指定连接
如果您有多个 LinkedIn 连接,请使用 Maton-Connection 头指定要使用的连接:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/linkedin/rest/me')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('LinkedIn-Version', '202506')
req.add_header('Maton-Connection', 'ba10eb9e-b590-4e95-8c2e-3901ff94642a')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
如果省略,网关将使用默认(最早的)活动连接。
个人资料 API
获取当前用户资料
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/linkedin/rest/me')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('LinkedIn-Version', '202506')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
响应示例:
{
"id": "123ABC",
"firstName": {
"localized": {
"en_US": "John"
}
},
"lastName": {
"localized": {
"en_US": "Doe"
}
},
"profilePicture": {
"displayImage": "urn:li:digitalmediaAsset:..."
}
}
获取组织信息
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/linkedin/rest/organizations/{organization_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('LinkedIn-Version', '202506')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
分享 API
创建文本帖子
python <<'EOF'
import urllib.request, os, json
data = json.dumps({
"author": "urn:li:person:123ABC",
"lifecycleState": "PUBLISHED",
"specificContent": {
"com.linkedin.ugc.ShareContent": {
"shareCommentary": {
"text": "Check out this amazing article about AI!"
},
"shareMediaCategory": "NONE"
}
},
"visibility": {
"com.linkedin.ugc.MemberNetworkVisibility": "PUBLIC"
}
}).encode()
req = urllib.request.Request('https://gateway.maton.ai/linkedin/rest/ugcPosts', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('LinkedIn-Version', '202506')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
创建带链接的帖子
python <<'EOF'
import urllib.request, os, json
data = json.dumps({
"author": "urn:li:person:123ABC",
"lifecycleState": "PUBLISHED",
"specificContent": {
"com.linkedin.ugc.ShareContent": {
"shareCommentary": {
"text": "Great read on machine learning trends in 2024"
},
"shareMediaCategory": "ARTICLE",
"media": [
{
"status": "READY",
"originalUrl": "https://example.com/article",
"title": {
"text": "ML Trends 2024"
}
}
]
}
},
"visibility": {
"com.linkedin.ugc.MemberNetworkVisibility": "CONNECTIONS"
}
}).encode()
req = urllib.request.Request('https://gateway.maton.ai/linkedin/rest/ugcPosts', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('LinkedIn-Version', '202506')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
广告 API
获取广告账户列表
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/linkedin/rest/adAccounts?q=search&search=')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('LinkedIn-Version', '202506')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
创建广告活动
python <<'EOF'
import urllib.request, os, json
data = json.dumps({
"name": "Summer Campaign 2024",
"account": "urn:li:sponsoredAccount:123456",
"objectiveType": "LEAD_GENERATION",
"runSchedule": {
"start": "2024-06-01",
"end": "2024-08-31"
},
"dailyBudget": {
"amount": 100,
"currencyCode": "USD"
}
}).encode()
req = urllib.request.Request('https://gateway.maton.ai/linkedin/rest/adCampaignsV2', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('LinkedIn-Version', '202506')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
媒体上传
上传图片
图片上传是一个三步过程:
- 初始化上传:
python <<'EOF'
import urllib.request, os, json
data = json.dumps({
"initializeUploadRequest": {
"owner": "urn:li:person:123ABC",
"recipes": ["urn:li:digitalmediaRecipe:feedshare-image"],
"serviceRelationships": [
{
"relationshipType": "OWNER",
"identifier": "urn:li:userGeneratedContent"
}
]
}
}).encode()
req = urllib.request.Request('https://gateway.maton.ai/linkedin/rest/media/upload', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('LinkedIn-Version', '202506')
req.add_header('Content-Type', 'application/json')
response = json.load(urllib.request.urlopen(req))
print(json.dumps(response, indent=2))
upload_url = response['value']['uploadMechanism']['com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest']['uploadUrl']
asset_urn = response['value']['asset']
EOF
- 上传二进制文件:
# 使用返回的 upload_url 直接上传(不通过网关)
python <<'EOF'
import urllib.request
with open('image.jpg', 'rb') as f:
data = f.read()
req = urllib.request.Request(upload_url, data=data, method='PUT')
req.add_header('Content-Type', 'image/jpeg')
urllib.request.urlopen(req)
EOF
- 创建帖子时引用图片:
# 在帖子中使用 asset_urn
广告库 API
搜索广告
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/linkedin/rest/adLibrary/search?q=search&keywords=AI')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('LinkedIn-Version', '202506')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Little Text Format 转义
LinkedIn 的评论字段使用 Little Text Format,某些字符需要转义:
| 字符 | 转义方式 | ||
|---|---|---|---|
\ | \\ | ||
| \ | ||
{ | \{ | ||
} | \} | ||
@ | \@ | ||
[ | \[ | ||
] | \] | ||
( | \( | ||
) | \) | ||
< | \< | ||
> | \> | ||
# | \# | ||
| \ | ||
_ | \_ | ||
~ | \~ |
话题标签(简单格式): #话题(仅限单个单词)
Python 辅助函数
def escape_linkedin_commentary(text): """转义 LinkedIn Little Text Format 的保留字符。""" reserved = ['\\', '|', '{', '}', '@', '[', ']', '(', ')', '<', '>', '#', '', '_', '~'] for char in reserved: text = text.replace(char, '\\' + char) return text
# 使用示例 commentary = escape_linkedin_commentary("Check this out! Details (inside) #tech") # 结果: "Check this out\\! Details \\(inside\\) \\#tech"
注意事项
- 人员 ID 是每个应用唯一的,不能跨应用转移
- 评论使用 Little Text Format — 使用反斜杠转义保留字符 (
\|{}@[]()<>#*_~),否则内容会被截断 author字段必须使用 URN 格式:urn:li:person:{personId}- 所有帖子都需要
lifecycleState: "PUBLISHED" - 图片上传是一个三步过程:初始化、上传二进制文件、创建帖子
- 视频上传是一个四步过程:初始化、上传二进制文件、完成、创建帖子
- 媒体上传 URL(图片、视频、文档)指向
www.linkedin.com,而不是api.linkedin.com。 这些是预签名 URL,不通过网关,不需要 Authorization 头。您必须使用 Pythonurllib来处理这些 URL — 不要通过 shell 变量传递或使用curl,因为 URL 包含会被 shell 扩展破坏的编码字符 (%253D)。 - 所有 REST API 调用都包含
LinkedIn-Version: 202506头 - 个人资料图片 URL 可能过期;如果需要请重新获取
错误处理
| 状态码 | 含义 |
|---|---|
| 400 | 缺少 LinkedIn 连接或请求无效 |
| 401 | Maton API 密钥无效或缺失 |
| 403 | 权限不足(检查 OAuth 作用域) |
| 404 | 资源未找到 |
| 422 | 请求体或 URN 格式无效 |
| 429 | 速率限制 |
| 4xx/5xx | LinkedIn API 的直通错误 |
错误响应格式
{
"status": 403,
"serviceErrorCode": 100,
"code": "ACCESS_DENIED",
"message": "Not enough permissions to access resource"
}
故障排除:API 密钥问题
- 检查
MATON_API_KEY环境变量是否设置:
echo $MATON_API_KEY
- 通过列出连接验证 API 密钥是否有效:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
故障排除:应用名称无效
- 确保您的 URL 路径以
linkedin开头。例如:
- 正确:
https://gateway.maton.ai/linkedin/rest/me - 错误:
https://gateway.maton.ai/rest/me
OAuth 作用域
| 作用域 | 描述 |
|---|---|
openid | OpenID Connect 认证 |
profile | 读取基本个人资料 |
email | 读取邮箱地址 |
w_member_social | 创建、修改和删除帖子 |