更新情報(2026年11月10日):書き方を見直しました。検証の結果とスクリプトは変えていません。
はじめに
棚卸しの前に、kintoneの全アプリのアクセス権をスクリプトで一覧にしようとしました。
検証用の環境には、アプリが6つあります。ところが、アプリの一覧API(/k/v1/apps.json)が返したのは5つでした。kintoneシステム管理者で実行しているのに、です。
原因を追っていくと、「全アプリを見た」つもりで抜ける所が、ほかにも3つ見つかりました。
結果
先に結果です。
| 抜けたところ | 防いだ方法 |
|---|---|
| 閲覧権限のないアプリが、一覧のAPIに出ない | 一覧にないアプリIDを1つずつ確かめる |
| ゲストスペースのアプリは、送り先が違う | ゲストスペースの送り先で取り直す |
| アクセス権は、上の行が優先される | 行の順番ごと残す |
| 1回きりの一覧では、前回と比べられない | 日付入りのファイルで残す |
4つまとめて防ぐスクリプトは、後半に載せています。
検証環境
- kintone(2026年11月6日時点)、kintoneシステム管理者のユーザー
- REST APIは、ブラウザのコンソールから実行
- アプリは6つ。アプリ5は、このユーザーにレコードの閲覧権限がないアプリ。アプリ6は、ゲストスペースのアプリ
1. 閲覧できないアプリは、一覧に出てこない
/k/v1/apps.json に出るのは、実行した人がレコードを閲覧(または追加)できるアプリだけでした。システム管理者でも変わりません。
閲覧権限のないアプリ5と、存在しないアプリ99に、3つのAPIを投げて比べました。
| API | アプリ5(閲覧権限なし) | アプリ99(存在しない) |
|---|---|---|
/k/v1/apps.json |
出ない | 出ない |
/k/v1/app.json |
CB_NO02(権限がありません) |
GAIA_AP01(見つかりません) |
/k/v1/app/acl.json |
読める | GAIA_AP01 |
アクセス権は読めるのに、一覧には出てこない。ここは意外でした。人事や経理のように、見る人を絞ったアプリほど抜けます。
一覧にないIDは、/k/v1/app.json で1つずつ確かめます。GAIA_AP01 以外が返ってきたら、そのアプリはあります。
2. ゲストスペースのアプリは、送り先が違う
ゲストスペースのアプリは、一覧には出ます。ただ、/k/v1/... に送ると GAIA_IL23 が返ってきます。
ここを「読めなかった」で済ませると、社外の人がいるスペースのアプリが点検から抜けます。一覧の spaceId を使って、送り先を /k/guest/(spaceId)/v1/... に変えると読めました。
3. アクセス権は、上の行が優先される
1人が複数の行に当てはまると、上の行の設定が使われます。
たとえば1行目が「Everyone:閲覧・編集」、2行目が「営業部:閲覧だけ」なら、営業部の人も編集できます。一覧にするときに行の順番を捨てると、ここを読み違えます。/k/v1/app/acl.json の rights は優先される順に返ってくるので、順番も一緒に残します。
4. 1回きりの一覧では、前回と比べられない
次の点検で聞かれるのは「前回から何が変わったか」です。画面に出すだけでは比べられません。
日付入りのファイルで残しておけば、次の点検で差分を取れます。jq が入っている環境なら、キーの順をそろえてから比べると読みやすくなります。
diff <(jq -S . kintone-acl-2026-11-06.json) <(jq -S . kintone-acl-2026-12-06.json)
4つまとめて防ぐスクリプト
kintoneのどれかのアプリの画面で、開発者ツールのコンソール(Windowsは Ctrl+Shift+J、Macは command+option+J)に貼り付けて実行します。読み取るだけなので、設定は変わりません。
(async () => {
// 1. アプリの一覧(apps.json)に出るアプリを、100件ずつ最後まで取る
const listed = [];
for (let offset = 0; ; offset += 100) {
const res = await kintone.api('/k/v1/apps.json', 'GET', { limit: 100, offset });
listed.push(...res.apps);
if (res.apps.length < 100) break;
}
const ids = new Set(listed.map((a) => Number(a.appId)));
const max = Math.max(0, ...ids);
// 2. 一覧に出ないアプリを、アプリIDから探す(ないIDは GAIA_AP01 が返る)
const hidden = [];
for (let id = 1; id <= max + 20; id++) {
if (ids.has(id)) continue;
try {
await kintone.api('/k/v1/app.json', 'GET', { id });
hidden.push({ appId: id, error: '' });
} catch (e) {
if (e.code !== 'GAIA_AP01') hidden.push({ appId: id, error: e.code });
}
}
// 3. アクセス権を取る。ゲストスペースのアプリ(GAIA_IL23)は、ゲストスペースの送り先で取り直す
const get = async (path, app) => {
try {
return await kintone.api(path, 'GET', { app: app.appId });
} catch (e) {
if (e.code !== 'GAIA_IL23' || !app.spaceId) throw e;
return kintone.api(path.replace('/k/v1/', `/k/guest/${app.spaceId}/v1/`), 'GET', { app: app.appId });
}
};
const RIGHTS = { appEditable: 'アプリ管理', recordViewable: '閲覧', recordAddable: '追加', recordEditable: '編集',
recordDeletable: '削除', recordImportable: '読み込み', recordExportable: '書き出し' };
const result = { takenAt: new Date().toISOString(), host: location.host, listed: listed.length, hidden, apps: {} };
for (const app of listed) {
try {
const { rights } = await get('/k/v1/app/acl.json', app);
result.apps[app.appId] = {
name: app.name,
// 上の行ほど優先されるので、順番を残す
rights: rights.map((r, i) => ({
order: i + 1,
target: r.entity.type + (r.entity.code ? ':' + r.entity.code : '') + (r.includeSubs ? '(下位組織を含む)' : ''),
can: Object.keys(RIGHTS).filter((k) => r[k]).map((k) => RIGHTS[k]).join('・') || 'なし',
})),
};
} catch (e) {
result.apps[app.appId] = { name: app.name, error: e.code };
}
}
// 4. 次の点検で前回と比べられるよう、日付入りのJSONで保存する
const day = result.takenAt.slice(0, 10);
const a = document.createElement('a');
a.href = URL.createObjectURL(new Blob([JSON.stringify(result, null, 2)], { type: 'application/json' }));
a.download = `kintone-acl-${day}.json`;
a.click();
const failed = Object.values(result.apps).filter((x) => x.error).length;
console.log(`一覧に出たアプリ ${listed.length}個/一覧に出ないアプリ ${hidden.length}個/読めなかったアプリ ${failed}個`);
})();
検証環境で実行すると kintone-acl-2026-11-06.json が保存され、コンソールにはこう出ました。
一覧に出たアプリ 5個/一覧に出ないアプリ 1個/読めなかったアプリ 0個
※ アクセス権を取れるのは、実行した人に「アプリ管理」の権限があるアプリだけです。取れなかったアプリは error に残ります。
※ 一覧にないアプリは、一覧の最大IDの先20個まで探します。足りなければ max + 20 を増やしてください。
※ レコードとフィールドのアクセス権も、/k/v1/record/acl.json と /k/v1/field/acl.json で同じように取れます。
点検の記録に残しておくこと
上司への報告や監査では、「どこまで見たか」を聞かれます。次の4つを残しておくと答えられます。
- 点検した日と、点検した人
- 一覧に出たアプリ・出なかったアプリ・読めなかったアプリ
- 見直す設定と、担当・期限
- 前回からの変更と、前回の指摘が直ったか
さいごに
一覧のAPIに出てこないアプリがある。知っていれば数行で防げますが、知らないと報告書に「全アプリを点検」と書いてしまいます。
筆者は、この点検を点検台帳(Excel)と報告書にまとめるkintoneのプラグイン「棚卸し・変更監視パック」を作っています(有料)。見直したほうがよい設定が何件あるかは、申し込みなしで確かめられます。
関連記事
- kintoneで退職者を利用停止にしても、アプリの設定には残る(2026年11月確認版)
- kintoneのプラグインが外部に送っていないかは、通信先のドメインだけでは分からない(2026年11月確認版)
- kintoneのアクセス権を一覧で確認する方法(アプリ・レコード・フィールド)(台帳屋の使い方ガイド)
- kintoneのアプリを棚卸しする方法(台帳屋の使い方ガイド)