perl-security
Perlのセキュリティ対策を網羅的にサポートするスキルで、汚染モード・入力バリデーション・安全なプロセス実行・DBIのパラメータ化クエリ・Web脆弱性(XSS/SQLi/CSRF)対策・perlcriticのセキュリティポリシー適用まで幅広く対応します。
description の原文を見る
全面的Perl安全指南,涵盖污染模式、输入验证、安全进程执行、DBI参数化查询、Web安全(XSS/SQLi/CSRF)以及perlcritic安全策略。
SKILL.md 本文
Perl セキュリティパターン
入力検証、インジェクション防止、安全なコーディング慣行をカバーするPerlアプリケーション向けの包括的なセキュリティガイド。
使用する場合
- Perlアプリケーションでユーザー入力を処理する場合
- Perl Webアプリケーションを構築する場合(CGI、Mojolicious、Dancer2、Catalyst)
- Perlコード内のセキュリティ脆弱性をレビューする場合
- ユーザー提供のパスを使用してファイル操作を実行する場合
- Perlからシステムコマンドを実行する場合
- DBIデータベースクエリを作成する場合
仕組み
汚染を認識した入力の境界から開始し、外側に拡張します:入力の検証と無害化を行い、ファイルシステムとプロセス実行を制限し、至るところでパラメータ化されたDBIクエリを使用します。以下の例は、ユーザー入力、シェル、ネットワークに関わるPerlコードを配信する前に、このスキルが適用を期待するセキュリティのデフォルト慣行を示しています。
汚染モード
Perlの汚染モード(-T)は外部ソースからのデータを追跡し、明示的に検証されるまでそれが危険な操作で使用されることを防止します。
汚染モードを有効化
#!/usr/bin/perl -T
use v5.36;
# Tainted: anything from outside the program
my $input = $ARGV[0]; # Tainted
my $env_path = $ENV{PATH}; # Tainted
my $form = <STDIN>; # Tainted
my $query = $ENV{QUERY_STRING}; # Tainted
# Sanitize PATH early (required in taint mode)
$ENV{PATH} = '/usr/local/bin:/usr/bin:/bin';
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
無害化パターン
use v5.36;
# Good: Validate and untaint with a specific regex
sub untaint_username($input) {
if ($input =~ /^([a-zA-Z0-9_]{3,30})$/) {
return $1; # $1 is untainted
}
die "Invalid username: must be 3-30 alphanumeric characters\n";
}
# Good: Validate and untaint a file path
sub untaint_filename($input) {
if ($input =~ m{^([a-zA-Z0-9._-]+)$}) {
return $1;
}
die "Invalid filename: contains unsafe characters\n";
}
# Bad: Overly permissive untainting (defeats the purpose)
sub bad_untaint($input) {
$input =~ /^(.*)$/s;
return $1; # Accepts ANYTHING — pointless
}
入力検証
ブロックリストよりもアロウリスト
use v5.36;
# Good: Allowlist — define exactly what's permitted
sub validate_sort_field($field) {
my %allowed = map { $_ => 1 } qw(name email created_at updated_at);
die "Invalid sort field: $field\n" unless $allowed{$field};
return $field;
}
# Good: Validate with specific patterns
sub validate_email($email) {
if ($email =~ /^([a-zA-Z0-9._%+-]+\@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})$/) {
return $1;
}
die "Invalid email address\n";
}
sub validate_integer($input) {
if ($input =~ /^(-?\d{1,10})$/) {
return $1 + 0; # Coerce to number
}
die "Invalid integer\n";
}
# Bad: Blocklist — always incomplete
sub bad_validate($input) {
die "Invalid" if $input =~ /[<>"';&|]/; # Misses encoded attacks
return $input;
}
長さの制約
use v5.36;
sub validate_comment($text) {
die "Comment is required\n" unless length($text) > 0;
die "Comment exceeds 10000 chars\n" if length($text) > 10_000;
return $text;
}
安全な正規表現
正規表現サービス拒否の防止
ネストされた量指定子が重複パターンに適用されると、カタストロフィックなバックトラッキングが発生します。
use v5.36;
# Bad: Vulnerable to ReDoS (exponential backtracking)
my $bad_re = qr/^(a+)+$/; # Nested quantifiers
my $bad_re2 = qr/^([a-zA-Z]+)*$/; # Nested quantifiers on class
my $bad_re3 = qr/^(.*?,){10,}$/; # Repeated greedy/lazy combo
# Good: Rewrite without nesting
my $good_re = qr/^a+$/; # Single quantifier
my $good_re2 = qr/^[a-zA-Z]+$/; # Single quantifier on class
# Good: Use possessive quantifiers or atomic groups to prevent backtracking
my $safe_re = qr/^[a-zA-Z]++$/; # Possessive (5.10+)
my $safe_re2 = qr/^(?>a+)$/; # Atomic group
# Good: Enforce timeout on untrusted patterns
use POSIX qw(alarm);
sub safe_match($string, $pattern, $timeout = 2) {
my $matched;
eval {
local $SIG{ALRM} = sub { die "Regex timeout\n" };
alarm($timeout);
$matched = $string =~ $pattern;
alarm(0);
};
alarm(0);
die $@ if $@;
return $matched;
}
セキュアなファイル操作
3引数 open
use v5.36;
# Good: Three-arg open, lexical filehandle, check return
sub read_file($path) {
open my $fh, '<:encoding(UTF-8)', $path
or die "Cannot open '$path': $!\n";
local $/;
my $content = <$fh>;
close $fh;
return $content;
}
# Bad: Two-arg open with user data (command injection)
sub bad_read($path) {
open my $fh, $path; # If $path = "|rm -rf /", runs command!
open my $fh, "< $path"; # Shell metacharacter injection
}
TOCTOU(Time-of-Check-Time-of-Use)とパストラバーサルの防止
use v5.36;
use Fcntl qw(:DEFAULT :flock);
use File::Spec;
use Cwd qw(realpath);
# Atomic file creation
sub create_file_safe($path) {
sysopen(my $fh, $path, O_WRONLY | O_CREAT | O_EXCL, 0600)
or die "Cannot create '$path': $!\n";
return $fh;
}
# Validate path stays within allowed directory
sub safe_path($base_dir, $user_path) {
my $real = realpath(File::Spec->catfile($base_dir, $user_path))
// die "Path does not exist\n";
my $base_real = realpath($base_dir)
// die "Base dir does not exist\n";
die "Path traversal blocked\n" unless $real =~ /^\Q$base_real\E(?:\/|\z)/;
return $real;
}
一時ファイルの処理に File::Temp を使用する(tempfile(UNLINK => 1))、および競合状態を防ぐために flock(LOCK_EX) を使用します。
セキュアなプロセス実行
リスト形式の system と exec
use v5.36;
# Good: List form — no shell interpolation
sub run_command(@cmd) {
system(@cmd) == 0
or die "Command failed: @cmd\n";
}
run_command('grep', '-r', $user_pattern, '/var/log/app/');
# Good: Capture output safely with IPC::Run3
use IPC::Run3;
sub capture_output(@cmd) {
my ($stdout, $stderr);
run3(\@cmd, \undef, \$stdout, \$stderr);
if ($?) {
die "Command failed (exit $?): $stderr\n";
}
return $stdout;
}
# Bad: String form — shell injection!
sub bad_search($pattern) {
system("grep -r '$pattern' /var/log/app/"); # If $pattern = "'; rm -rf / #"
}
# Bad: Backticks with interpolation
my $output = `ls $user_dir`; # Shell injection risk
Capture::Tiny を使用して、外部コマンドの標準出力と標準エラーを安全にキャプチャすることもできます。
SQLインジェクション防止
DBIプレースホルダー
use v5.36;
use DBI;
my $dbh = DBI->connect($dsn, $user, $pass, {
RaiseError => 1,
PrintError => 0,
AutoCommit => 1,
});
# Good: Parameterized queries — always use placeholders
sub find_user($dbh, $email) {
my $sth = $dbh->prepare('SELECT * FROM users WHERE email = ?');
$sth->execute($email);
return $sth->fetchrow_hashref;
}
sub search_users($dbh, $name, $status) {
my $sth = $dbh->prepare(
'SELECT * FROM users WHERE name LIKE ? AND status = ? ORDER BY name'
);
$sth->execute("%$name%", $status);
return $sth->fetchall_arrayref({});
}
# Bad: String interpolation in SQL (SQLi vulnerability!)
sub bad_find($dbh, $email) {
my $sth = $dbh->prepare("SELECT * FROM users WHERE email = '$email'");
# If $email = "' OR 1=1 --", returns all users
$sth->execute;
return $sth->fetchrow_hashref;
}
動的カラムのアロウリスト
use v5.36;
# Good: Validate column names against an allowlist
sub order_by($dbh, $column, $direction) {
my %allowed_cols = map { $_ => 1 } qw(name email created_at);
my %allowed_dirs = map { $_ => 1 } qw(ASC DESC);
die "Invalid column: $column\n" unless $allowed_cols{$column};
die "Invalid direction: $direction\n" unless $allowed_dirs{uc $direction};
my $sth = $dbh->prepare("SELECT * FROM users ORDER BY $column $direction");
$sth->execute;
return $sth->fetchall_arrayref({});
}
# Bad: Directly interpolating user-chosen column
sub bad_order($dbh, $column) {
$dbh->prepare("SELECT * FROM users ORDER BY $column"); # SQLi!
}
DBIx::Class(ORMセキュリティ)
use v5.36;
# DBIx::Class generates safe parameterized queries
my @users = $schema->resultset('User')->search({
status => 'active',
email => { -like => '%@example.com' },
}, {
order_by => { -asc => 'name' },
rows => 50,
});
Webセキュリティ
XSS防止
use v5.36;
use HTML::Entities qw(encode_entities);
use URI::Escape qw(uri_escape_utf8);
# Good: Encode output for HTML context
sub safe_html($user_input) {
return encode_entities($user_input);
}
# Good: Encode for URL context
sub safe_url_param($value) {
return uri_escape_utf8($value);
}
# Good: Encode for JSON context
use JSON::MaybeXS qw(encode_json);
sub safe_json($data) {
return encode_json($data); # Handles escaping
}
# Template auto-escaping (Mojolicious)
# <%= $user_input %> — auto-escaped (safe)
# <%== $raw_html %> — raw output (dangerous, use only for trusted content)
# Template auto-escaping (Template Toolkit)
# [% user_input | html %] — explicit HTML encoding
# Bad: Raw output in HTML
sub bad_html($input) {
print "<div>$input</div>"; # XSS if $input contains <script>
}
CSRF保護
use v5.36;
use Crypt::URandom qw(urandom);
use MIME::Base64 qw(encode_base64url);
sub generate_csrf_token() {
return encode_base64url(urandom(32));
}
トークン検証時は一定時間比較を使用します。ほとんどのWebフレームワーク(Mojolicious、Dancer2、Catalyst)は組み込みのCSRF保護を提供しているため、これらを優先し、自家製のソリューションではなく利用します。
セッションとヘッダーセキュリティ
use v5.36;
# Mojolicious session + headers
$app->secrets(['long-random-secret-rotated-regularly']);
$app->sessions->secure(1); # HTTPS only
$app->sessions->samesite('Lax');
$app->hook(after_dispatch => sub ($c) {
$c->res->headers->header('X-Content-Type-Options' => 'nosniff');
$c->res->headers->header('X-Frame-Options' => 'DENY');
$c->res->headers->header('Content-Security-Policy' => "default-src 'self'");
$c->res->headers->header('Strict-Transport-Security' => 'max-age=31536000; includeSubDomains');
});
出力エンコーディング
常にコンテキストに応じて出力をエンコードします:HTMLの場合は HTML::Entities::encode_entities()、URLの場合は URI::Escape::uri_escape_utf8()、JSONの場合は JSON::MaybeXS::encode_json() を使用します。
CPANモジュールセキュリティ
- cpanfile内でバージョンを固定:
requires 'DBI', '== 1.643'; - メンテナンス中のモジュールを優先:MetaCPANで最新リリースをチェック
- 依存関係を最小化:各依存関係は攻撃面です
セキュリティツール
perlcritic セキュリティポリシー
# .perlcriticrc — security-focused configuration
severity = 3
theme = security + core
# Require three-arg open
[InputOutput::RequireThreeArgOpen]
severity = 5
# Require checked system calls
[InputOutput::RequireCheckedSyscalls]
functions = :builtins
severity = 4
# Prohibit string eval
[BuiltinFunctions::ProhibitStringyEval]
severity = 5
# Prohibit backtick operators
[InputOutput::ProhibitBacktickOperators]
severity = 4
# Require taint checking in CGI
[Modules::RequireTaintChecking]
severity = 5
# Prohibit two-arg open
[InputOutput::ProhibitTwoArgOpen]
severity = 5
# Prohibit bare-word filehandles
[InputOutput::ProhibitBarewordFileHandles]
severity = 5
perlcritic実行
# Check a file
perlcritic --severity 3 --theme security lib/MyApp/Handler.pm
# Check entire project
perlcritic --severity 3 --theme security lib/
# CI integration
perlcritic --severity 4 --theme security --quiet lib/ || exit 1
セキュリティ確認チェックリスト(クイック版)
| チェック項目 | 検証内容 |
|---|---|
| 汚染モード | CGI/Webスクリプトで -T フラグを使用 |
| 入力検証 | アロウリストパターン、長さ制限 |
| ファイル操作 | 3引数open、パストラバーサルチェック |
| プロセス実行 | system のリスト形式、シェル補間なし |
| SQLクエリ | DBIプレースホルダー、補間なし |
| HTML出力 | encode_entities()、テンプレート自動エスケープ |
| CSRFトークン | トークン生成、状態変更リクエストで検証 |
| セッション設定 | セキュア、HttpOnly、SameSite Cookie |
| HTTPヘッダー | CSP、X-Frame-Options、HSTS |
| 依存関係 | バージョン固定、監査済みモジュール |
| 正規表現セキュリティ | ネストされた量指定子なし、パターンはアンカー付き |
| エラーメッセージ | ユーザーにスタックトレースやパスを漏らさない |
アンチパターン
# 1. Two-arg open with user data (command injection)
open my $fh, $user_input; # CRITICAL vulnerability
# 2. String-form system (shell injection)
system("convert $user_file output.png"); # CRITICAL vulnerability
# 3. SQL string interpolation
$dbh->do("DELETE FROM users WHERE id = $id"); # SQLi
# 4. eval with user input (code injection)
eval $user_code; # Remote code execution
# 5. Trusting $ENV without sanitizing
my $path = $ENV{UPLOAD_DIR}; # Could be manipulated
system("ls $path"); # Double vulnerability
# 6. Disabling taint without validation
($input) = $input =~ /(.*)/s; # Lazy untaint — defeats purpose
# 7. Raw user data in HTML
print "<div>Welcome, $username!</div>"; # XSS
# 8. Unvalidated redirects
print $cgi->redirect($user_url); # Open redirect
記憶しておく:Perlの柔軟性は強力ですが、規律が必要です。Webファイシング向けのコードで汚染モードを使用し、すべての入力をアロウリスト検証で処理し、各クエリでDBIプレースホルダーを使用し、コンテキストに応じてすべての出力をエンコードします。多層防御を行う——決して単一の防御層に依存しないこと。
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- affaan-m
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/affaan-m/everything-claude-code / ライセンス: MIT
関連スキル
secure-code-guardian
認証・認可の実装、ユーザー入力の保護、OWASP Top 10の脆弱性対策が必要な場合に使用します。bcrypt/argon2によるパスワードハッシング、パラメータ化ステートメントによるSQLインジェクション対策、CORS/CSPヘッダーの設定、Zodによる入力検証、JWTトークンの構築などのカスタムセキュリティ実装に対応します。認証、認可、入力検証、暗号化、OWASP Top 10対策、セッション管理、セキュリティ強化全般で活用できます。ただし、構築済みのOAuth/SSO統合や単独のセキュリティ監査が必要な場合は、より特化したスキルの検討をお勧めします。
claude-authenticity
APIエンドポイントが本物のClaudeによって支えられているか(ラッパーやプロキシ、偽装ではないか)を、claude-verifyプロジェクトを模した9つの重み付きルールベースチェックで検証できます。また、Claudeの正体を上書きしているプロバイダーから注入されたシステムプロンプトも抽出します。完全に自己完結しており、httpx以外の追加パッケージは不要です。Claude APIキーまたはエンドポイントを検証したい場合、サードパーティのClaudeサービスが本物か確認したい場合、APIプロバイダーのClaude正当性を監査したい場合、複数モデルを並行してテストしたい場合、またはプロバイダーが注入したシステムプロンプトを特定したい場合に使用できます。
anth-security-basics
Anthropic Claude APIのセキュリティベストプラクティスを適用し、キー管理、入力値の検証、プロンプトインジェクション対策を実施します。APIキーの保護、Claudeに送信する前のユーザー入力検証、コンテンツセーフティガードレールの実装が必要な場合に活用できます。「anthropic security」「claude api key security」「secure anthropic」「prompt injection defense」といったフレーズでトリガーされます。
x-ray
x-ray.mdプレ監査レポートを生成します。概要、強化された脅威モデル(プロトコルタイプのプロファイリング、Gitの重み付け攻撃面分析、時間軸リスク分析、コンポーザビリティ依存関係マッピング)、不変条件、統合、ドキュメント品質、テスト分析、開発者・Gitの履歴をカバーしています。「x-ray」「audit readiness」「readiness report」「pre-audit report」「prep this protocol」「protocol prep」「summarize this protocol」のキーワードで実行されます。
semgrep
Semgrepスタティック分析スキャンを実行し、カスタム検出ルールを作成します。Semgrepでのコードスキャン、セキュリティ脆弱性の検出、カスタムYAMLルールの作成、または特定のバグパターンの検出が必要な場合に使用します。重要:ユーザーが「バグをスキャンしたい」「コード品質を確認したい」「脆弱性を見つけたい」「スタティック分析」「セキュリティlint」「コード監査」または「コーディング標準を適用したい」と尋ねた場合も、Semgrepという名称を明記していなくても、このスキルを使用してください。Semgrepは30以上の言語に対応したパターンベースのコードスキャンに最適なツールです。
ghost-bits-cast-attack
Java「ゴーストビッツ」/キャストアタック プレイブック(Black Hat Asia 2026)。16ビット文字が8ビットバイトに暗黙的に縮小されるJavaサービスへの攻撃時に使用します。WAF/IDSを回避して、SQLインジェクション、デシリアライゼーション型RCE、ファイルアップロード(Webシェル)、パストトラバーサル、CRLF インジェクション、リクエストスマグリング、SMTPインジェクションを実行できます。Tomcat、Spring、Jetty、Undertow、Vert.x、Jackson、Fastjson、Apache Commons BCEL、Apache HttpClient、Angus Mail、JDK HttpServer、Lettuce、Jodd、XMLWriterに影響し、WAFバイパスにより多くの「パッチ済み」CVEを再度有効化します。