[アップデート]GuardDuty Malware Protection for S3のEventBridge通知にstatusReasonsフィールドが追加されました

[アップデート]GuardDuty Malware Protection for S3のEventBridge通知にstatusReasonsフィールドが追加されました

2026.04.22

はじめに

GuardDuty Malware Protection for S3 について調査していたところ、EventBridge 通知に statusReasons フィールドが追加されていました。

Updated functionality - Malware Protection for S3
The EventBridge notification for S3 object scan results now includes a statusReasons field in scanResultDetails when a scan is skipped. This field provides the specific reason why the scan was skipped. For more information, see S3 object potential scan status and result status.
Document history for Amazon GuardDuty - Amazon GuardDuty

GuardDuty Malware Protection for S3 は、S3 バケットにアップロードされたオブジェクトを自動でマルウェアスキャンしてくれるサービスです。

https://dev.classmethod.jp/articles/release-guardduty-s3-malware-protection/

スキャン結果は EventBridge 通知で受け取れるのですが、スキャンがスキップされた場合に「なぜスキップされたのか」がわからないという課題がありました。

statusReasons フィールドが追加され、スキップ理由が EventBridge 通知のペイロードで確認できるようになりました。

何が嬉しいのか

これまでは scanStatus: SKIPPED の通知を受け取っても、scanResultStatusUNSUPPORTEDACCESS_DENIED かはわかる程度でした。

これがアップデートのstatusReasons の追加で、通知ペイロードだけで具体的な理由コードがわかるようになっています。

statusReasons は新規追加フィールドなので、既存の EventBridge ルールパターンはそのまま動作します。
追加の設定も不要で、GuardDuty が自動的にペイロードに含めてくれます。

statusReasons全コード一覧

statusReasonsscanStatusSKIPPED の場合のみ値が入ります。COMPLETEDFAILED の場合は null です。

全コードの一覧は以下ドキュメントに記載があります。
Monitoring S3 object scans in Malware Protection for S3 - Amazon GuardDuty

ACCESS_DENIED系

コード 説明 対処法
UNAUTHORIZED_TO_GET_OBJECT IAMロールにs3:GetObject権限がない、またはオブジェクトが存在しない IAMロールポリシーとKMSポリシーを確認
UNAUTHORIZED_TO_ASSUME_ROLE GuardDutyがIAMロールをAssumeできない ロールの信頼ポリシーを確認
SSE_C_ENCRYPTED_OBJECT SSE-C暗号化オブジェクトはスキャン不可 SSE-S3/SSE-KMSへの移行を検討
OBJECT_E_TAG_CHANGED スキャン開始後にETagが変化した 次回アップロード時に自動再スキャンされるため対処不要
BUCKET_NOT_FOUND 保護対象バケットが削除済み Malware Protection Planを再設定

UNSUPPORTED系

コード 説明 対処法
UNSUPPORTED_STORAGE_CLASS Glacier等のサポート外ストレージクラス Standardクラスに変更
OBJECT_SIZE_LIMIT_EXCEEDED ファイルサイズ上限(100 GB)超過 ファイル分割を検討
PASSWORD_PROTECTED パスワード保護されたファイル セキュリティチームへ確認依頼
EXTRACTED_FILE_LIMIT_EXCEEDED アーカイブ内ファイル数が上限(10,000)超過 アーカイブ前にスキャンを推奨
EXTRACTED_LEVEL_LIMIT_EXCEEDED アーカイブのネスト深度が上限(5)超過 圧縮レベルを制限
EXTRACTED_BYTE_LIMIT_EXCEEDED 展開後バイトサイズが上限(100 GB)超過 ファイル分割を検討
EXTRACTION_RATIO_LIMIT_EXCEEDED 圧縮率が極端に高い(ZIP爆弾対策) セキュリティアラート対象

やってみる

パスワード付き ZIP ファイルをアップロードして、実際に EventBridge 通知で statusReasons が返ってくることを確認してみます。
CloudWatch Logs にイベントを出力して確認します。

S3バケットの作成

テスト用の S3 バケットを作成します。

BUCKET_NAME="guardduty-malware-test-$(date +%Y%m%d)-${RANDOM}"
REGION="ap-northeast-1"

aws s3 mb s3://${BUCKET_NAME} --region ${REGION}

IAMロールの作成

Malware Protection for S3 がスキャンに使用する IAM ロールを作成します。

trust-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "malware-protection-plan.guardduty.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
aws iam create-role \
  --role-name GuardDutyMalwareS3ScanRole \
  --assume-role-policy-document file://trust-policy.json

続いて、S3 バケットへのアクセス権限や EventBridge 管理ルールの権限を付与します。

ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
scan-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowGetObject",
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:GetObjectVersion",
        "s3:GetBucketLocation",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::${BUCKET_NAME}",
        "arn:aws:s3:::${BUCKET_NAME}/*"
      ]
    },
    {
      "Sid": "AllowTagging",
      "Effect": "Allow",
      "Action": [
        "s3:PutObjectTagging",
        "s3:GetObjectTagging",
        "s3:PutObjectVersionTagging",
        "s3:GetObjectVersionTagging"
      ],
      "Resource": "arn:aws:s3:::${BUCKET_NAME}/*"
    },
    {
      "Sid": "AllowEventBridge",
      "Effect": "Allow",
      "Action": [
        "s3:PutBucketNotification",
        "s3:GetBucketNotification"
      ],
      "Resource": "arn:aws:s3:::${BUCKET_NAME}"
    },
    {
      "Sid": "AllowManagedRule",
      "Effect": "Allow",
      "Action": [
        "events:PutRule",
        "events:DeleteRule",
        "events:PutTargets",
        "events:RemoveTargets"
      ],
      "Resource": "arn:aws:events:${REGION}:${ACCOUNT_ID}:rule/DO-NOT-DELETE-AmazonGuardDutyMalwareProtectionS3*",
      "Condition": {
        "StringEquals": {
          "events:ManagedBy": "malware-protection-plan.guardduty.amazonaws.com"
        }
      }
    },
    {
      "Sid": "AllowPutValidationObject",
      "Effect": "Allow",
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::${BUCKET_NAME}/malware-protection-resource-validation-object"
    }
  ]
}
aws iam put-role-policy \
  --role-name GuardDutyMalwareS3ScanRole \
  --policy-name MalwareScanPolicy \
  --policy-document file://scan-policy.json

Malware Protection Planの作成

ROLE_ARN="arn:aws:iam::${ACCOUNT_ID}:role/GuardDutyMalwareS3ScanRole"

aws guardduty create-malware-protection-plan \
  --role "${ROLE_ARN}" \
  --protected-resource "{\"S3Bucket\": {\"BucketName\": \"${BUCKET_NAME}\"}}" \
  --actions '{"Tagging": {"Status": "ENABLED"}}' \
  --region ${REGION}

レスポンスで malwareProtectionPlanId が返ってくるので控えておきます。
この時点で設定された対象のバケットが確認できます。

Screenshot 2026-04-22 午前8.43.30.png

EventBridgeルールの作成

今回は結果をログで確認するので、スキャン結果を CloudWatch Logs に送信する EventBridge ルールを作成します。

aws events put-rule \
  --name "GuardDuty-Malware-ScanResult-Test" \
  --event-pattern '{
    "source": ["aws.guardduty"],
    "detail-type": ["GuardDuty Malware Protection Object Scan Result"]
  }' \
  --state ENABLED \
  --region ${REGION}

ターゲットに CloudWatch Logs を設定します。

LOG_GROUP="/aws/events/guardduty-malware-scan-results"

aws logs create-log-group \
  --log-group-name ${LOG_GROUP} \
  --region ${REGION}

aws events put-targets \
  --rule "GuardDuty-Malware-ScanResult-Test" \
  --targets "Id=CloudWatchTarget,Arn=arn:aws:logs:${REGION}:${ACCOUNT_ID}:log-group:${LOG_GROUP}" \
  --region ${REGION}

パスワード付きZIPをアップロードしてSKIPPEDを発生させる

パスワード付き ZIP ファイルを作成してアップロードします。

echo "test file content" > test-for-zip.txt
zip --password testpass protected.zip test-for-zip.txt
aws s3 cp protected.zip s3://${BUCKET_NAME}/test/protected.zip

パスワード保護されたファイルは Malware Protection for S3 でスキャンできないため、SKIPPED になるはずです。

EventBridge通知でstatusReasonsを確認

数分待ってから CloudWatch Logs を確認します。

aws logs filter-log-events \
  --log-group-name ${LOG_GROUP} \
  --region ${REGION} \
  --query 'events[].message' \
  --output text | jq .

以下のようなイベントが確認できます。

{
    "version": "0",
    "id": "07ed0777-041d-4fc2-b715-531f361128ab",
    "detail-type": "GuardDuty Malware Protection Object Scan Result",
    "source": "aws.guardduty",
    "account": "111122223333",
    "time": "2026-04-21T00:28:52Z",
    "region": "ap-northeast-1",
    "resources": [
        "arn:aws:guardduty:ap-northeast-1:111122223333:malware-protection-plan/aaced6b73065bb4d60d4"
    ],
    "detail": {
        "schemaVersion": "1.0",
        "scanStatus": "SKIPPED",
        "resourceType": "S3_OBJECT",
        "s3ObjectDetails": {
            "bucketName": "guardduty-malware-test-20260421-26391",
            "objectKey": "test/protected.zip",
            "eTag": "6741c9decf4e31ddd6ac768e21f39686",
            "versionId": null,
            "s3Throttled": false
        },
        "scanResultDetails": {
            "scanResultStatus": "UNSUPPORTED",
            "threats": null,
            "statusReasons": [
                "PASSWORD_PROTECTED"
            ]
        }
    }
}

scanResultDetails.statusReasonsPASSWORD_PROTECTED が入っていますね。

Screenshot 2026-04-22 午前8.42.05.png

scanResultStatus: UNSUPPORTED だけではわからなかった詳細な理由が、statusReasons で明確になりました。
「パスワード保護されたファイルだからスキップされた」と即座に判断できますね。

S3 オブジェクトのタグも確認してみます。

aws s3api get-object-tagging \
  --bucket ${BUCKET_NAME} \
  --key test/protected.zip
{
  "TagSet": [
    {
      "Key": "GuardDutyMalwareScanStatus",
      "Value": "UNSUPPORTED"
    }
  ]
}

タグ側には UNSUPPORTED が記録されています。タグはあくまでスキャン結果のサマリで、詳細な理由コードは EventBridge 通知の statusReasons で確認する形になります。

まとめ

GuardDuty Malware Protection for S3 の EventBridge 通知に statusReasons フィールドが追加されました。
スキャンのスキップ理由を特定できるようになっています。既存環境への影響はなく、追加設定も不要です。

スキップ理由に応じた自動対処フローを組むことで、セキュリティ運用の効率化に役立ちそうです。
Malware Protection for S3 をお使いの方は、ぜひ EventBridge ルールで statusReasons を活用してみてください。

以上、鈴木純がお送りしました。

参考

この記事をシェアする

関連記事