Configure Notifications
The English user guide is currently in beta preview. Most of the documents have been automatically translated from the Japanese version. Should you find any inaccuracies, please reach out to Flatt Security.
Shisho Cloud provides two types of notification features: Real-time Notifications and Project Report Notifications.
- Real-time Notifications: Sent when issues are detected or triaged, triggered by state changes.
- Project Report Notifications: Periodically summarize the current security status for each project.
This page explains how to configure each notification type.
Comparison of Notification Features
The following table summarizes the characteristics of each notification feature. Use them according to your needs.
| Feature | Real-time Notifications | Project Report Notifications |
|---|---|---|
| Primary Use Case | Notifications when issues are detected or triaged | Periodic security status reporting |
| Notification Trigger | When issues are detected or triaged | Scheduled (daily/weekly/monthly) |
| Notification Content | Individual issues | Project-wide summary and breakdown |
| Configuration Method | Controlled via workflows | Configured via project settings page |
| Customizability | High (flexible control via workflows) | Medium (controlled via settings) |
Usage Examples:
- Real-time Notifications: Send Slack notifications when Critical/High severity issues are found, or create tickets in your ticketing system.
- Project Report Notifications: Receive daily email reports of the entire project's security status for review in regular meetings.
Configure Real-time Notifications
Real-time notifications are sent when issues are detected or triaged, triggered by state changes.
Shisho Cloud allows you to flexibly control the timing and content of notifications through workflows. For ease of use without complex configuration, a default notification workflow is provided, which sends notifications based on the severity of detected issues.
Example Slack Notification

Example Email Notification

Notification Workflows
There are two types of notification workflows: organization-wide notifications and project-specific notifications. Both send notifications when issues are detected or triaged.
- Notification Workflow
- Per-Project Notification Workflow
The notification workflow is a standard workflow included in Shisho Cloud. It sends notifications when issues are detected or triaged for all resources within the organization, using the following delivery methods:
- Notifications to Slack channels
- Emails to designated addresses
- Notifications to destinations associated with notification groups
Some users may have a workflow distributed that only supports Slack notifications. In that case, please open the standard notification workflow page, copy and paste the following new workflow to replace the existing one. After replacing the workflow, you will need to specify the notification destinations again. Please specify them in the parameter settings on the standard notification workflow page.
id: notification-security
name: "Prebundle: Notify important security events in a variety of ways"
version: 0.1.0
triggers:
triage:
- event:
- updated
status_changed_to:
- awaiting_review
- acknowledged
- action_required
- secure
- deleted
- event:
- created
status_changed_to:
- awaiting_review
jobs:
- id: triage
name: Notify triage status updation
notify:
rego: |
package notification.triage
import data.shisho
import data.shisho.notification.slack
import data.shisho.notification.group
minimum_severity := severity_intl(data.params.minimum_severity) {
data.params
data.params.minimum_severity != ""
} else := shisho.decision.severity_critical
severity_intl(x) := shisho.decision.severity_info {
x == "INFO"
} else := shisho.decision.severity_low {
x == "LOW"
} else := shisho.decision.severity_medium {
x == "MEDIUM"
} else := shisho.decision.severity_high {
x == "HIGH"
} else := shisho.decision.severity_critical {
x == "CRITICAL"
} else := shisho.decision.severity_low
severity_string(x) := "参考情報(info)" {
x == shisho.decision.severity_info
} else := "低(low)" {
x == shisho.decision.severity_low
} else := "中(medium)" {
x == shisho.decision.severity_medium
} else := "高(high)" {
x == shisho.decision.severity_high
} else := "緊急(critical)" {
x == shisho.decision.severity_critical
} else := x
severity_emoji(x) := ":information_source:" {
x == shisho.decision.severity_info
} else := ":eyes:" {
x == shisho.decision.severity_low
} else := ":warning:" {
x == shisho.decision.severity_medium
} else := ":rotating_light:" {
x == shisho.decision.severity_high
} else := ":sos:" {
x == shisho.decision.severity_critical
} else := ":memo:"
triage_status(x) := "要レビュー" {
x == "AWAITING_REVIEW"
} else := "要対応" {
x == "ACTION_REQUIRED"
} else := "リスク受容中" {
x == "ACKNOWLEDGED"
} else := "セキュア" {
x == "SECURE"
} else := "削除済" {
x == "DELETED"
} else := x
triage_status_emoji(x) := ":eyes:" {
x == "AWAITING_REVIEW"
} else := ":heavy_exclamation_mark:" {
x == "ACTION_REQUIRED"
} else := ":arrow_right:" {
x == "ACKNOWLEDGED"
} else := ":large_green_circle:" {
x == "SECURE"
} else := ":wastebasket:" {
x == "DELETED"
} else := ":memo:"
title(explanation, api_version, kind) := explanation.title {
explanation
} else := "" {
concat(":", [api_version, kind])
}
slack_headline(type, status) := "*新たなポリシー違反が検出されました。*\n対応を検討しましょう。" {
type == "CREATED"
} else := "*ポリシー違反が解決されました* :tada:" {
type == "UPDATED"
status == "SECURE"
} else := "*ポリシーに違反した設定の対応状況が変化しました。*\n引き続き対応を進めましょう。"
slack_triage_information(target) := [
slack.divider_block,
slack.context_block([slack.text_element(concat("", [":mega: トリアージ者: ", target.triageInitiator.displayName]))]),
slack.context_block([slack.text_element(concat("", [":memo: コメント: ", target.triageComment]))]),
] {
target.triageInitiator.displayName != ""
target.triageComment != ""
} else := [
slack.divider_block,
slack.context_block([slack.text_element(concat("", [":mega: トリアージ者: ", target.triageInitiator.displayName]))]),
] {
target.triageInitiator.displayName != ""
target.triageComment == ""
} else := []
# send notifications by Slack
notifications[n] {
# send notification only if the channel is specified
data.params.slack_channel != ""
workspace_id := split(data.params.slack_channel, ":")[0]
channel_id := split(data.params.slack_channel, ":")[1]
event := input.query.shisho.event
event.__typename == "ShishoTriageStatusEvent"
input.running_state == shisho.job.running_state_preprocessing
# send notification only if the severity of the target decision is higher than the minimum severity
target_severity := severity_intl(event.target.severity)
minimum_severity <= target_severity
n := shisho.notification.to_slack_channel(
workspace_id,
channel_id,
{"blocks": array.concat(
[slack.text_section(
slack_headline(event.type, event.status),
{"fields": [
# The first row
slack.text_element("*:memo: 違反が見られた観点*"),
slack.text_element("*:dart: 対象リソース*"),
slack.text_element(concat("", ["<", event.target.viewer, "|", title(event.target.explanation, event.target.apiVersion, event.target.kind), ">"])),
slack.text_element(concat("", ["<", event.target.subject.viewer, "|", event.target.subject.displayName, ">"])),
# The second row
slack.text_element(concat("", [severity_emoji(target_severity), " *重大度*"])),
slack.text_element(concat("", [triage_status_emoji(event.status), " *対応状況*"])),
slack.text_element(severity_string(target_severity)),
slack.text_element(concat("", ["*", triage_status(event.status), "* に変化しました"])),
]},
)],
# The footer
array.concat(slack_triage_information(event.target), [
slack.divider_block,
slack.context_block([slack.text_element(concat("", [":shield: *Powered by \"<", event.target.createdBy.viewer, "|", event.target.createdBy.name, ">\" on Shisho Cloud*"]))]),
slack.divider_block,
]),
)},
)
}
headline(type, status) := "新たなポリシー違反が検出されました。対応を検討しましょう。" {
type == "CREATED"
} else := "ポリシー違反が解決されました" {
type == "UPDATED"
status == "SECURE"
} else := "ポリシーに違反した設定の対応状況が変化しました。引き続き対応を進めましょう。"
triage_information(target) := [
concat("", ["トリアージ者: ", target.triageInitiator.displayName, "\n"]),
concat("", ["コメント: ", target.triageComment, "\n"]),
] {
target.triageInitiator.displayName != ""
target.triageComment != ""
} else := [
concat("", ["トリアージ者: ", target.triageInitiator.displayName, "\n"]),
] {
target.triageInitiator.displayName != ""
target.triageComment == ""
} else := []
# send notifications by email
notifications[n] {
# send notification only if the email address is specified
data.params.email_address != ""
email = data.params.email_address
event := input.query.shisho.event
event.__typename == "ShishoTriageStatusEvent"
input.running_state == shisho.job.running_state_preprocessing
# send notification only if the severity of the target decision is higher than the minimum severity
target_severity := severity_intl(event.target.severity)
minimum_severity <= target_severity
n := shisho.notification.to_email(
email,
concat("", [
headline(event.type, event.status),
"\n\n",
"違反が見られた観点: ",
concat("", [title(event.target.explanation, event.target.apiVersion, event.target.kind), " (", event.target.viewer, ")", "\n"]),
"対象リソース: ",
concat("", [event.target.subject.displayName, " (", event.target.subject.viewer, ")", "\n"]),
"重大度: ",
severity_string(target_severity),
"\n",
"対応状況: ",
concat("", [triage_status(event.status), "に変化しました", "\n"]),
"\n",
concat("", triage_information(event.target)),
"\n",
concat("", ["Powered by \"", event.target.createdBy.name, " (", event.target.createdBy.viewer, ")", "\" on Shisho Cloud"]),
]),
)
}
# send notifications with a notification group
notifications[n] {
# send notification only if the notification group ID is specified
data.params.notification_group != ""
group_id = data.params.notification_group
event := input.query.shisho.event
event.__typename == "ShishoTriageStatusEvent"
input.running_state == shisho.job.running_state_preprocessing
# send notification only if the severity of the target decision is higher than the minimum severity
target_severity := severity_intl(event.target.severity)
minimum_severity <= target_severity
n := shisho.notification.to_group(
group_id,
concat("", [
headline(event.type, event.status),
"\n\n",
"違反が見られた観点: ",
concat("", [title(event.target.explanation, event.target.apiVersion, event.target.kind), " (", event.target.viewer, ")", "\n"]),
"対象リソース: ",
concat("", [event.target.subject.displayName, " (", event.target.subject.viewer, ")", "\n"]),
"重大度: ",
severity_string(target_severity),
"\n",
"対応状況: ",
concat("", [triage_status(event.status), "に変化しました", "\n"]),
"\n",
concat("", triage_information(event.target)),
"\n",
concat("", ["Powered by \"", event.target.createdBy.name, " (", event.target.createdBy.viewer, ")", "\" on Shisho Cloud"]),
]),
)
}
input:
schema: |
query {
shisho {
event {
__typename
... on ShishoTriageStatusEvent {
type
status
target {
apiVersion
kind
subject {
displayName
parentDisplayName
viewer
}
severity
viewer
explanation(locale: JA_JP) {
title
description
}
createdBy {
name
viewer
}
triageComment
triageInitiator {
id
type
displayName
}
}
}
}
}
}
with:
slack_channel:
type: slack_channel
descrition: The Slack channel to send notifications.
value: ""
email_address:
type: string
descrition: The email channel to send notifications.
value: ""
notification_group:
type: notification_target
descrition: The notification group to send notifications.
value: ""
minimum_severity:
type: string
description: The minimum severity to notify.
value: HIGH
oneof:
- INFO
- LOW
- MEDIUM
- HIGH
- CRITICAL
The per-project notification workflow sends notifications to various destinations when issues are detected or triaged within the scope (resources) of a project. This workflow is not included by default, so if necessary, please copy and create a new workflow using the following YAML:
version: 0.1.0
id: "notification-project-security"
name: "Prebundle: Notify Shisho Cloud project's important security events"
triggers:
triage:
# send notifications when...
- event: [updated]
status_changed_to:
# the issue is calling your review.
- awaiting_review
# the issue is acknowledged, and no further action is not expected.
- acknowledged
# the issue is marked to need your fix.
- action_required
# the issue was fixed :tada:
- secure
# the resource with security issue(s) gets deleted.
- deleted
# send notifications on a finding needs your action
- event: [created]
status_changed_to:
- awaiting_review
jobs:
- id: triage
name: Notify triage status updation
notify:
rego: |
package notification.project_security.triage
import data.shisho
import data.shisho.notification.slack
import data.shisho.notification.group
minimum_severity := severity_intl(data.params.minimum_severity) {
data.params
data.params.minimum_severity != ""
} else := shisho.decision.severity_critical
severity_intl(x) := shisho.decision.severity_info {
x == "INFO"
} else := shisho.decision.severity_low {
x == "LOW"
} else := shisho.decision.severity_medium {
x == "MEDIUM"
} else := shisho.decision.severity_high {
x == "HIGH"
} else := shisho.decision.severity_critical {
x == "CRITICAL"
} else := shisho.decision.severity_low
severity_string(x) := "参考情報(info)" {
x == shisho.decision.severity_info
} else := "低(low)" {
x == shisho.decision.severity_low
} else := "中(medium)" {
x == shisho.decision.severity_medium
} else := "高(high)" {
x == shisho.decision.severity_high
} else := "緊急(critical)" {
x == shisho.decision.severity_critical
} else := x
severity_emoji(x) := ":information_source:" {
x == shisho.decision.severity_info
} else := ":eyes:" {
x == shisho.decision.severity_low
} else := ":warning:" {
x == shisho.decision.severity_medium
} else := ":rotating_light:" {
x == shisho.decision.severity_high
} else := ":sos:" {
x == shisho.decision.severity_critical
} else := ":memo:"
triage_status(x) := "要レビュー" {
x == "AWAITING_REVIEW"
} else := "要対応" {
x == "ACTION_REQUIRED"
} else := "リスク受容中" {
x == "ACKNOWLEDGED"
} else := "セキュア" {
x == "SECURE"
} else := "削除済" {
x == "DELETED"
} else := x
triage_status_emoji(x) := ":eyes:" {
x == "AWAITING_REVIEW"
} else := ":heavy_exclamation_mark:" {
x == "ACTION_REQUIRED"
} else := ":arrow_right:" {
x == "ACKNOWLEDGED"
} else := ":large_green_circle:" {
x == "SECURE"
} else := ":wastebasket:" {
x == "DELETED"
} else := ":memo:"
title(explanation, api_version, kind) := explanation.title {
explanation
} else := "" {
concat(":", [api_version, kind])
}
slack_headline(type, status) := "*新たなポリシー違反が検出されました。*\n対応を検討しましょう。" {
type == "CREATED"
} else := "*ポリシー違反が解決されました* :tada:" {
type == "UPDATED"
status == "SECURE"
} else := "*ポリシーに違反した設定の対応状況が変化しました。*\n引き続き対応を進めましょう。"
slack_triage_information(target) := [
slack.divider_block,
slack.context_block([slack.text_element(concat("", [":mega: トリアージ者: ", target.triageInitiator.displayName]))]),
slack.context_block([slack.text_element(concat("", [":memo: コメント: ", target.triageComment]))]),
] {
target.triageInitiator.displayName != ""
target.triageComment != ""
} else := [
slack.divider_block,
slack.context_block([slack.text_element(concat("", [":mega: トリアージ者: ", target.triageInitiator.displayName]))]),
] {
target.triageInitiator.displayName != ""
target.triageComment == ""
} else := []
# send notifications by Slack
notifications[n] {
event := input.query.shisho.event
event.__typename == "ShishoTriageStatusEvent"
input.running_state == shisho.job.running_state_preprocessing
# send a notification only if the severity of the target decision is higher than the minimum severity
target_severity := severity_intl(event.target.severity)
minimum_severity <= target_severity
# send a notification to the default project notification channels
project := event.target.subject.projectsBelongingTo[_]
channel := project.defaultNotificationChannels[_]
channel.__typename == "ShishoNotificationChannelSlack"
n := shisho.notification.to_slack_channel(
channel.workspaceId,
channel.channelId,
{"blocks": array.concat(
[slack.text_section(
slack_headline(event.type, event.status),
{"fields": [
# The first row
slack.text_element("*:memo: 違反が見られた観点*"),
slack.text_element("*:dart: 対象リソース*"),
slack.text_element(concat("", ["<", event.target.viewer, "|", title(event.target.explanation, event.target.apiVersion, event.target.kind), ">"])),
slack.text_element(concat("", ["<", event.target.subject.viewer, "|", event.target.subject.displayName, ">"])),
# The second row
slack.text_element(concat("", [severity_emoji(target_severity), " *重大度*"])),
slack.text_element(concat("", [triage_status_emoji(event.status), " *対応状況*"])),
slack.text_element(severity_string(target_severity)),
slack.text_element(concat("", ["*", triage_status(event.status), "* に変化しました"])),
]},
)],
# The footer
array.concat(slack_triage_information(event.target), [
slack.divider_block,
slack.context_block([slack.text_element(concat("", [":shield: *Powered by \"<", event.target.createdBy.viewer, "|", event.target.createdBy.name, ">\" on Shisho Cloud*"]))]),
slack.divider_block,
]),
)},
)
}
headline(type, status) := "新たなポリシー違反が検出されました。対応を検討しましょう。" {
type == "CREATED"
} else := "ポリシー違反が解決されました" {
type == "UPDATED"
status == "SECURE"
} else := "ポリシーに違反した設定の対応状況が変化しました 。引き続き対応を進めましょう。"
triage_information(target) := [
concat("", ["トリアージ者: ", target.triageInitiator.displayName, "\n"]),
concat("", ["コメント: ", target.triageComment, "\n"]),
] {
target.triageInitiator.displayName != ""
target.triageComment != ""
} else := [
concat("", ["トリアージ者: ", target.triageInitiator.displayName, "\n"]),
] {
target.triageInitiator.displayName != ""
target.triageComment == ""
} else := []
# send notifications by email
notifications[n] {
event := input.query.shisho.event
event.__typename == "ShishoTriageStatusEvent"
input.running_state == shisho.job.running_state_preprocessing
# send a notification only if the severity of the target decision is higher than the minimum severity
target_severity := severity_intl(event.target.severity)
minimum_severity <= target_severity
# send a notification to the default project notification channels
project := event.target.subject.projectsBelongingTo[_]
channel := project.defaultNotificationChannels[_]
channel.__typename == "ShishoNotificationChannelEmail"
n := shisho.notification.to_email(
channel.email,
concat("", [
headline(event.type, event.status),
"\n\n",
"違反が見られた観点: ",
concat("", [title(event.target.explanation, event.target.apiVersion, event.target.kind), " (", event.target.viewer, ")", "\n"]),
"対象リソース: ",
concat("", [event.target.subject.displayName, " (", event.target.subject.viewer, ")", "\n"]),
"重大度: ",
severity_string(target_severity),
"\n",
"対応状況: ",
concat("", [triage_status(event.status), "に変化しました", "\n"]),
"\n",
concat("", triage_information(event.target)),
"\n",
concat("", ["Powered by \"", event.target.createdBy.name, " (", event.target.createdBy.viewer, ")", "\" on Shisho Cloud"]),
]),
)
}
# send notifications with a notification group
notifications[n] {
event := input.query.shisho.event
event.__typename == "ShishoTriageStatusEvent"
input.running_state == shisho.job.running_state_preprocessing
# send a notification only if the severity of the target decision is higher than the minimum severity
target_severity := severity_intl(event.target.severity)
minimum_severity <= target_severity
# send a notification to the default project notification channels
project := event.target.subject.projectsBelongingTo[_]
channel := project.defaultNotificationChannels[_]
channel.__typename == "ShishoNotificationChannelGroup"
n := shisho.notification.to_group(
channel.id,
concat("", [
headline(event.type, event.status),
"\n\n",
"違反が見られた観点: ",
concat("", [title(event.target.explanation, event.target.apiVersion, event.target.kind), " (", event.target.viewer, ")", "\n"]),
"対象リソース: ",
concat("", [event.target.subject.displayName, " (", event.target.subject.viewer, ")", "\n"]),
"重大度: ",
severity_string(target_severity),
"\n",
"対応状況: ",
concat("", [triage_status(event.status), "に変化しました", "\n"]),
"\n",
concat("", triage_information(event.target)),
"\n",
concat("", ["Powered by \"", event.target.createdBy.name, " (", event.target.createdBy.viewer, ")", "\" on Shisho Cloud"]),
]),
)
}
input:
schema: |
query {
shisho {
event {
__typename
... on ShishoTriageStatusEvent {
type
status
target {
apiVersion
kind
subject {
displayName
parentDisplayName
viewer
projectsBelongingTo {
id
name
defaultNotificationChannels {
__typename
... on ShishoNotificationChannelSlack {
workspaceId
channelId
name
}
... on ShishoNotificationChannelGroup {
id
name
}
... on ShishoNotificationChannelEmail {
email
}
}
}
}
severity
viewer
explanation(locale: JA_JP) {
title
description
}
createdBy {
name
viewer
}
triageComment
triageInitiator {
id
type
displayName
}
}
}
}
}
}
with:
minimum_severity:
type: string
description: The minimum severity to notify.
value: HIGH
oneof:
- INFO
- LOW
- MEDIUM
- HIGH
- CRITICAL
Let's take a look at how to configure notifications.
Configuring the Notification Workflow
This section explains how to modify the notification workflow settings and configure notifications for when issues are detected and triaged.
Accessing the Notification Workflow Settings Page
Go to the notification workflow editing page. You should see the following screen:

Editing Parameters
In the upper right corner of the screen, you'll find settings for various notification destinations and the severity levels of detected issues that trigger notifications. Configure each item and click Save.

To configure notifications, you need to configure various notification targets beforehand. For details, see here.
Testing Slack Notifications
To use Slack channel notifications, you can send a test notification by clicking the Send Test Notification button. If you see a message like the one below, your notification settings are complete.

Configuring Per-Project Notification Workflows
In some cases, you may want to send notifications to the same destination, while in other cases, you may want to send notifications to different destinations for each project. In such cases, use the per-project notification workflow described above.
Accessing the Settings Page of the Target Project
First, from the project list screen, select the project you want to configure notifications for and go to the settings page.

Configuring Notification Destinations
On the settings page, select the desired notification destination and add or update it.

The following can currently be added as project notification destinations. Each of these needs to be configured in advance, so if your desired notification destination is not displayed as an option, please check the configuration.
- Slack channels: See "Setting Up Slack Notifications" in Notification Targets.
- Notification groups: See Configuring Notification Groups.
- Email: See "Setting Up Email Notifications" in Notification Targets.
Accessing the Per-Project Notification Workflow Settings Page
Since you have already configured the notification destinations on the project settings page, you do not need to configure them again using parameters. If you want to change the severity of detected issues that trigger notifications, go to the per-project notification workflow edit page and edit the parameters.

Configure Project Report Notifications
Project report notifications periodically send security status reports for your projects. Select the target project from the project list and open the settings page.
Example Slack Notification

Example Email Notification

Configure Notification Destinations
Notifications are sent to the default notification destinations for each project. If you haven't registered any yet, please register notification destinations.

If no notification destinations are configured, notifications will not be sent even if this feature is enabled. Please register at least one notification destination.
Enable and Configure Project Report Notifications
In the notification settings, turn on the toggle for the notifications you want to receive. Currently, we provide a "Security Status Report by Resource Kind" that aggregates findings by resource kind.
Security Status Report by Resource Kind Configuration
You can configure the following settings. Change them as needed and click the Save button.

Currently, only daily reports are supported. Weekly and monthly reports will be supported in the future.
Reports only include findings with the status Awaiting Review or Action Needed.
For email notifications, if the HTML email exceeds a certain size, it will automatically be sent in plain text format. Please be aware of this in advance.