dataiotech Labs
dbaguidedbaguideDBAdataxtoolsdataopsphere
Home/Hata Teşhis Kütüphanesi/postgresql-permission-denied-for-table
PostgreSQL
PostgreSQL 14–18Güvenlik & Yetkilendirme
7 dk okuma
ERROR: permission denied for table / relation (SQLSTATE 42501)

PostgreSQL "permission denied for table" — Hangi Rol, Hangi Yetki Eksik?

permission denied hatasında dört yetki katmanı: şema USAGE, tablo yetkisi, sequence ve search_path. PG 15 sonrası public şema değişikliği.

İnceleyen:Principal Database Reliability Architect
Test Edilen Sürümler: PostgreSQL 18.6, 17.11 & 15.6 (Alpine Linux / Docker 29.7) | Tarihsel: PostgreSQL 14 (public schema grant farkı)

Operasyonel Doğrulama & Güvenilirlik Standardı

Son Teknik İnceleme: 30 Ekim 2026
Test Edilen SürümlerPostgreSQL 18.6, 17.11 & 15.6 (Alpine / Ubuntu) | PostgreSQL 14.10 (öncesi/sonrası public CREATE)
Gerekli YetkiTablo/şema sahibi veya SUPERUSER (yetkileri GRANT / ALTER DEFAULT PRIVILEGES ile düzenlemek için)
Risk Seviyesi
MediumAşırı geniş GRANT ALL yetkisi vermek en az yetki (least privilege) güvenlik prensibini bozar
Beklenen Çıktıhas_schema_privilege, has_table_privilege ve has_sequence_privilege sorgularının true dönmesi ve 0 hata
Geri Dönüş (Rollback) Planı:REVOKE ile fazla yetkileri geri alıp ALTER DEFAULT PRIVILEGES FOR ROLE ile rol bazlı kontrollü yetki verme
PostgreSQL Docs: Privileges & Default Privileges
İlk 60 Saniye Teşhis Protokolü:

Hata mesajı semptomdur, kök neden değildir. Sunucuyu yeniden başlatmadan veya rastgele ayar değiştirmeden önce aşağıdaki "Nedeni ayırt eden tek sorgu"yu çalıştırarak gerçek senaryoyu netleştirin.

▸Belirti

plaintext
ERROR: permission denied for table siparis ERROR: permission denied for sequence siparis_id_seq ERROR: permission denied for schema public ERROR: permission denied for relation siparis

SQLSTATE hata kodu: 42501 (insufficient_privilege).

Dört farklı nesne türü, dört farklı yetkilendirme katmanını temsil eder. Hepsi aynı "permission denied" sözcükleriyle başladığı için çoğu mühendis hepsine rastgele GRANT ALL uygular ve güvenlik açığı yaratır veya sequence katmanını atladığı için yine başarısız olur.

ÖNEMLİ
PostgreSQL 15 Kırıcı Değişikliği (Breaking Change): PostgreSQL 15 sürümünde güvenlik sertleştirmesi yapıldı: PUBLIC sahte-rolünün public şeması üzerindeki varsayılan CREATE yetkisi tamamen kaldırıldı. PostgreSQL 14 ve öncesinde sorunsuz çalışan migration scriptleri, PostgreSQL 15'e geçildiğinde aniden permission denied for schema public hatası verir. Bu sayfanın en sık ziyaret edilme sebebi bu mimari değişikliktir.

▸Nedenini Doğrulayan Teşhis Sorguları

Önce havuzlayıcı veya ORM oturumunun sizi gerçekte hangi kimlikle bağladığını görün:

sql
SELECT current_user, session_user, current_setting('search_path');

Ardından yetkileri tek tek katalog tablolarından aramak yerine PostgreSQL'in yerleşik doğrulama fonksiyonlarıyla sorgulayın:

sql
SELECT has_schema_privilege('app_user', 'public', 'USAGE') AS sema_usage, has_table_privilege('app_user', 'public.siparis', 'SELECT') AS tablo_select, has_table_privilege('app_user', 'public.siparis', 'INSERT') AS tablo_insert, has_table_privilege('app_user', 'public.siparis', 'UPDATE') AS tablo_update, has_sequence_privilege('app_user', 'public.siparis_id_seq', 'USAGE') AS seq_usage;

Hangi sütun false dönüyorsa eksik olan yetki katmanı odur. Bu tek sorgu deneme-yanılma turlarını anında bitirir.


▸Dört Yetki Katmanı ve Kritik Tuzaklar

1. Şema USAGE Yetkisi

Şema üzerinde USAGE yetkisi olmadan içindeki hiçbir tabloya veya fonksiyona erişilemez. Tabloda GRANT ALL verilmiş olsa dahi şema USAGE eksikse bu hata patlar:

sql
GRANT USAGE ON SCHEMA public TO app_user;

2. Tablo DML Yetkisi

SELECT, INSERT, UPDATE, DELETE. Tuzak: Bir tabloda UPDATE çalıştırabilmek için WHERE koşulundaki kolonları okumak gerekir; dolayısıyla yalnızca UPDATE verip SELECT vermemek pratik dünyada sorgunun reddedilmesine neden olur.

3. Sequence (Dizi) Yetkisi — En Çok Unutulan Katman!

Tablonuzda serial veya GENERATED BY DEFAULT AS IDENTITY kolonu varsa, yeni bir satır eklemek (INSERT) yalnızca tablo yetkisiyle tamamlanamaz; arka plandaki sequence nesnesinde de USAGE, SELECT yetkisi gerekir:

sql
GRANT USAGE, SELECT ON SEQUENCE public.siparis_id_seq TO app_user;

4. search_path Çözümleme Tuzağı

Eğer veritabanınızda birden fazla şemada (public.siparis ve muhasebe.siparis) aynı isimli tablolar varsa, PostgreSQL nesneyi search_path sırasına göre çözümler:

sql
SELECT to_regclass('siparis');

Eğer sorgu sizin yetkili olduğunuz tabloya değil, search_path içinde daha önde yer alan yetkisiz olduğunuz diğer şemadaki tabloya çözümleniyorsa sorun yetki değil arama yoludur.


▸Adım Adım Kalıcı Çözüm

1. En Az Yetki Prensibiyle Açıkça Yetki Verin

sql
GRANT USAGE ON SCHEMA public TO app_user; GRANT SELECT, INSERT, UPDATE, DELETE ON public.siparis TO app_user; GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO app_user;

2. Gelecekte Oluşturulacak Tabloları Unutmayın!

Bugün verilen yetkiler yarın migration çalıştırılıp oluşturulan yeni tabloları kapsamaz. Bu durum, "dün gece deploy ettik, sabah sistem permission denied verdi" vakalarının ana sebebidir:

sql
ALTER DEFAULT PRIVILEGES FOR ROLE app_owner IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_user; ALTER DEFAULT PRIVILEGES FOR ROLE app_owner IN SCHEMA public GRANT USAGE, SELECT ON SEQUENCES TO app_user;
UYARI
FOR ROLE app_owner ifadesi son derece kritiktir. Varsayılan yetkiler yalnızca o rol tarafından oluşturulan nesneler için geçerli olur. Migration scriptleriniz süperkullanıcı (postgres) ile çalışıyorsa, FOR ROLE postgres tanımlanmadığı sürece bu kural işlemez!

3. Sahip (Owner) ile Uygulama Kullanıcısını Ayırın

Veritabanı nesnelerinin sahibi DDL çalıştıran app_owner, uygulamanın bağlandığı kullanıcı ise yalnızca DML çalıştıran app_user olmalıdır. Bu ayrım, yazılımdaki bir SQL injection açığında uygulamanın DROP TABLE çalıştırmasını yapısal olarak imkansız kılar.


▸İlgili Hata Rehberleri & Hub Bağlantıları

Diğer Veritabanı Hata Teşhisleri

Kriz anında başvurabileceğiniz diğer doğrulanmış hata rehberleri.

Tüm Hatalar (50)